call to eggs call to eggs enclosing scopes and nonlocals shared global state may be what we want in some cases if we really want per-function counterthoughwe can either use classes as beforeor make use of closure ( factoryfunctions and the nonlocal statement in python xdescribed in because this new statement allows enclosing function scope variables to be changedthey can serve as per-decoration and changeable data in onlydef tracer(func)state via enclosing scope and nonlocal calls instead of class attrs or global def wrapper(*args**kwargs)calls is per-functionnot global nonlocal calls calls + print('call % to % (callsfunc __name__)return func(*args**kwargsreturn wrapper @tracer def spam(abc)print( csame asspam tracer(spam@tracer def eggs(xy)print( *ysame aseggs tracer(eggsspam( spam( = = = really calls wrapperbound to func wrapper calls spam eggs( eggs( = really calls wrapperbound to eggs nonlocal calls _is_ per-decoration here nowbecause enclosing scope variables are not cross-program globalseach wrapped function gets its own counter againjust as for classes and attributes here' the new output when run under xc:\codepy - decorator py call to spam call to spam call to eggs call to eggs coding function decorators