self calls self meth meth def __get__(selfinstanceowner)on method fetch def wrapper(*args**kwargs)on method callproxy with self+inst self calls + print('call % to % (self callsself meth __name__)return self meth(instance*args**kwargsreturn wrapper class person@tracer def giveraise(selfpercent)applies to class methods giveraise tracer(giveraisemakes giveraise descriptor @tracer def spam(abc)but fails for simple functions spam tracer(spamno attribute fetch occurs here in the rest of this we're going to be fairly casual about using classes or functions to code our function decoratorsas long as they are applied only to functions some decorators may not require the instance of the original classand will still work on both functions and methods if coded as class--something like python' own staticme thod decoratorfor examplewouldn' require an instance of the subject class (indeedits whole point is to remove the instance from the callthe moral of this storythoughis that if you want your decorators to work on both simple functions and methodsyou're probably better off using the nested-functionbased coding pattern outlined here instead of class with call interception timing calls to sample the fuller flavor of what function decorators are capable oflet' turn to different use case our next decorator times calls made to decorated function--both the time for one calland the total time among all calls the decorator is applied to two functionsin order to compare the relative speed of list comprehensions and the map built-in callfile timerdeco py caveatrange still differs list in xan iterable in caveattimer won' work on methods as coded (see quiz solutionimport timesys force list if sys version_info[ = else (lambda xxclass timerdef __init__(selffunc)self func func self alltime def __call__(self*args**kargs)start time clock(result self func(*args**kargscoding function decorators