A Timing Decorator (Python)

vegaseat 3 Tallied Votes 2K Views Share

With the advent of Python33 the module time has received a high resolution timer/counter. Here we use time.perf_counter() in a decorator to conveniently time two test functions.

Gribouillis commented: very nice +14
''' timing_decorator_perf.py
uses high speed time.perf_counter() new in python3.3
returned value is in fractional seconds
timing of 2 common sort algorithms
tested with Python33/34  by  vegaseat  17oct2014
'''

import time
from functools import wraps

def print_timing(func):
    '''
    create a timing decorator function
    use
    @print_timing
    just above the function you want to time
    '''
    @wraps(func)  # improves debugging
    def wrapper(*arg):
        start = time.perf_counter()  # needs python3.3 or higher
        result = func(*arg)
        end = time.perf_counter()
        fs = '{} took {:.3f} microseconds'
        print(fs.format(func.__name__, (end - start)*1000000))
        return result
    return wrapper

@print_timing
def insertion_sort(mylist):
    items = mylist[:]  # copy list
    for i in range(1, len(items)):
        j = i
        while j > 0 and items[j] < items[j-1]:
            items[j], items[j-1] = items[j-1], items[j]  # swap
            j -= 1
    return items

@print_timing
def selection_sort(mylist):
    items = mylist[:]  # copy list
    for i in range(0, len(items)-1):
        mn = min(range(i, len(items)), key=items.__getitem__)
        items[i], items[mn] = items[mn], items[i]   # swap
    return items

mylist = [8, 10, 6, 7, 4, 12, 5, 9, 1, 15, 3, 2]
newlist = insertion_sort(mylist)
print(newlist)

print('-'*40)

newlist2 = selection_sort(mylist)
print(newlist2)

''' result ...
insertion_sort took 28.225 microseconds
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15]
----------------------------------------
selection_sort took 30.150 microseconds
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15]
'''