runs __get__ then __call__ runs tracer __get__ firstbecause the giveraise attribute in the person class has been rebound to descriptor by the method function decorator the call expression then triggers the __call__ method of the returned wrapper objectwhich in turn invokes tracer __call__ in other wordsdecorated method calls trigger four-step processtracer __get__followed by three call operations-wrapper __call__tracer __call__and finally the original wrapped method the wrapper object retains both descriptor and subject instancesso it can route control back to the original decorator/descriptor class instance in effectthe wrapper object saves the subject class instance available during method attribute fetch and adds it to the later call' arguments listwhich is passed to the decorator__call__ routing the call back to the descriptor class instance this way is required in this application so that all calls to wrapped method use the same calls counter state information in the descriptor instance object alternativelywe could use nested function and enclosing scope references to achieve the same effect--the following version works the same as the preceding oneby swapping class and object attributes for nested function and scope references it requires noticeably less codebut follows the same four-step process on each decorated method callclass tracer(object)def __init__(selffunc)on decorator self calls save func for later call self func func def __call__(self*args**kwargs)on call to original func self calls + print('call % to % (self callsself func __name__)return self func(*args**kwargsdef __get__(selfinstanceowner)on method fetch def wrapper(*args**kwargs)retain both inst return self(instance*args**kwargsruns __call__ return wrapper add print statements to these alternativesmethods to trace the multistep get/call process on your ownand run them with the same test code as in the nested function alternative shown earlier (see file calltracer-descr py for their sourcein either codingthis descriptor-based scheme is also substantially subtler than the nested function optionand so is probably second choice here to be more bluntif its complexity doesn' send you screaming into the nightits performance costs probably shouldstillthis may be useful coding pattern in other contexts it' also worth noting that we might code this descriptor-based decorator more simply as followsbut it would then apply only to methodsnot to simple functions--an intrinsic limitation of attribute descriptors (and just the inverse of the problem we're trying to solveapplication to both functions and methodsclass tracer(object)def __init__(selfmeth) decorators for methodsbut not functionson decorator