questionswhere their visibility outside callables becomes an asset as changeable state associated with context of usethey are equivalent to enclosing scope nonlocals as usualchoosing from multiple tools is an inherent part of the programming task because decorators often imply multiple levels of callablesyou can combine functions with enclosing scopesclasses with attributesand function attributes to achieve variety of coding structures as we'll see laterthoughthis sometimes may be subtler than you expect--each decorated function should have its own stateand each decorated class may require state both for itself and for each generated instance in factas the next section will explain in more detailif we want to apply function decorators to class-level methodstoowe also have to be careful about the distinction python makes between decorators coded as callable class instance objects and decorators coded as functions class blunders idecorating methods when wrote the first class-based tracer function decorator in decorator py earlieri naively assumed that it could also be applied to any method--decorated methods should work the samei reasonedbut the automatic self instance argument would simply be included at the front of *args the only real downside to this assumption is that it is completely wrongwhen applied to class' methodthe first version of the tracer failsbecause self is the instance of the decorator class and the instance of the decorated subject class is not included in *args at all this is true in both python and introduced this phenomenon earlier in this but now we can see it in the context of realistic working code given the class-based tracing decoratorclass tracerdef __init__(selffunc)on decorator self calls save func for later call self func func def __call__(self*args**kwargs)on call to original function self calls + print('call % to % (self callsself func __name__)return self func(*args**kwargsdecoration of simple functions works as advertised earlier@tracer def spam(abc)print( cspam( call to spam spam( = = = call to spam spam tracer(spamtriggers tracer __init__ runs tracer __call__ spam saved in an instance attribute coding function decorators