Online Book Reader

Home Category

Learning Python - Mark Lutz [560]

By Root 1569 0
through the following quiz. Because this chapter was mostly focused on its larger examples, its quiz will ask you to modify some of its code in order to review.

Test Your Knowledge: Quiz

As mentioned in one of this chapter’s Notes, the timer function decorator with decorator arguments that we wrote in the section Adding Decorator Arguments can be applied only to simple functions, because it uses a nested class with a __call__ operator overloading method to catch calls. This structure does not work for class methods because the decorator instance is passed to self, not the subject class instance. Rewrite this decorator so that it can be applied to both simple functions and class methods, and test it on both functions and methods. (Hint: see the section Class Blunders I: Decorating Class Methods for pointers.) Note that you may make use of assigning function object attributes to keep track of total time, since you won’t have a nested class for state retention and can’t access nonlocals from outside the decorator code.

The Public/Private class decorators we wrote in this chapter will add overhead to every attribute fetch in a decorated class. Although we could simply delete the @ decoration line to gain speed, we could also augment the decorator itself to check the __debug__ switch and perform no wrapping at all when the –O Python flag is passed on the command line (just as we did for the argument range-test decorators). That way, we can speed our program without changing its source, via command-line arguments (python –O main.py...). Code and test this extension.

Test Your Knowledge: Answers

Here’s one way to code the first question’s solution, and its output (albeit with class methods that run too fast to time). The trick lies in replacing nested classes with nested functions, so the self argument is not the decorator’s instance, and assigning the total time to the decorator function itself so it can be fetched later through the original rebound name (see the section State Information Retention Options of this chapter for details—functions support arbitrary attribute attachment, and the function name is an enclosing scope reference in this context).import time

def timer(label='', trace=True): # On decorator args: retain args

def onDecorator(func): # On @: retain decorated func

def onCall(*args, **kargs): # On calls: call original

start = time.clock() # State is scopes + func attr

result = func(*args, **kargs)

elapsed = time.clock() - start

onCall.alltime += elapsed

if trace:

format = '%s%s: %.5f, %.5f'

values = (label, func.__name__, elapsed, onCall.alltime)

print(format % values)

return result

onCall.alltime = 0

return onCall

return onDecorator

# Test on functions

@timer(trace=True, label='[CCC]==>')

def listcomp(N): # Like listcomp = timer(...)(listcomp)

return [x * 2 for x in range(N)] # listcomp(...) triggers onCall

@timer(trace=True, label='[MMM]==>')

def mapcall(N):

return list(map((lambda x: x * 2), range(N))) # list() for 3.0 views

for func in (listcomp, mapcall):

result = func(5) # Time for this call, all calls, return value

func(5000000)

print(result)

print('allTime = %s\n' % func.alltime) # Total time for all calls

# Test on methods

class Person:

def __init__(self, name, pay):

self.name = name

self.pay = pay

@timer()

def giveRaise(self, percent): # giveRaise = timer()(giveRaise)

self.pay *= (1.0 + percent) # tracer remembers giveRaise

@timer(label='**')

def lastName(self): # lastName = timer(...)(lastName)

return self.name.split()[-1] # alltime per class, not instance

bob = Person('Bob Smith', 50000)

sue = Person('Sue Jones', 100000)

bob.giveRaise(.10)

sue.giveRaise(.20) # runs onCall(sue, .10)

print(bob.pay, sue.pay)

print(bob.lastName(), sue.lastName()) # runs onCall(bob), remembers lastName

print('%.5f %.5f' % (Person.giveRaise.alltime, Person.lastName.alltime))

# Expected output

[CCC]==>listcomp: 0.00002, 0.00002

[CCC]==>listcomp: 1.19636, 1.19638

[0, 2, 4, 6, 8]

allTime = 1.19637775192

[MMM]==>mapcall: 0.00002,

Return Main Page Previous Page Next Page

®Online Book Reader