File: decorator1.py

"""
timer function decorator examples
run me under Python 2.6 or 3.0
"""


import time

class timer:
    def __init__(self, func):
        self.func    = func
        self.alltime = 0
    def __call__(self, *args, **kargs):
        start   = time.clock()
        result  = self.func(*args, **kargs)
        elapsed = time.clock() - start
        self.alltime += elapsed
        print('%s: %.5f, %.5f' % (self.func.__name__, elapsed, self.alltime))
        return result


#
# caveat: map() returns an iterator in 3.0: use list(map()) to force 
# it to build a list like the list comprehension does, but don't do
# so in 2.6 -- would build two lists, not one; range() is an iterator
# in 3.0 too, so results for 2.6 and 3.0 won't compare directly;
#

if __name__ == '__main__':
    import sys

    @timer
    def listcomp(N):
        return [x * 2 for x in range(N)]

    if sys.version_info[0] == 2:
        @timer
        def mapcall(N):
            return map((lambda x: x * 2), range(N))
    else:
        @timer
        def mapcall(N):
            return list(map((lambda x: x * 2), range(N)))

    result = listcomp(5)       # time for this call, all calls, return value
    listcomp(50000)
    listcomp(500000)
    listcomp(1000000)   
    print(result)
    print('allTime = %s' % listcomp.alltime)      # total time for all comp calls

    print('')
    result = mapcall(5)
    mapcall(50000)
    mapcall(500000)
    mapcall(1000000)
    print(result)
    print('allTime = %s' % mapcall.alltime)       # total time for all map calls

    print('map/comp = %s' % round(mapcall.alltime / listcomp.alltime, 3))


############################################################################

# add constructor arguments


def timer(label='', trace=True):
    class Timer:
        def __init__(self, func):
            self.func    = func
            self.alltime = 0
        def __call__(self, *args, **kargs):
            start   = time.clock()
            result  = self.func(*args, **kargs)
            elapsed = time.clock() - start
            self.alltime += elapsed
            if trace:
                format = '%s %s: %.5f, %.5f'
                values = (label, self.func.__name__, elapsed, self.alltime)
                print(format % values)
            return result
    return Timer


if __name__ == '__main__':
    import sys

    @timer(trace=True, label='[CCC]==>')
    def listcomp(N):
        return [x * 2 for x in range(N)]

    if sys.version_info[0] == 2:
        @timer(trace=True, label='[MMM]==>')
        def mapcall(N):
            return map((lambda x: x * 2), range(N))
    else:
        @timer(trace=True, label='[MMM]==>')
        def mapcall(N):
            return list(map((lambda x: x * 2), range(N)))

    for func in (listcomp, mapcall):
        print('')
        result = func(5)        # time for this call, all calls, return value
        func(50000)
        func(500000)
        func(1000000)
        print(result)  
        print('allTime = %s' % func.alltime)   # total time for all calls

    print('map/comp = %s' % round(mapcall.alltime / listcomp.alltime, 3))



[Home page] Books Code Blog Python Author Train Find ©M.Lutz