do not require new-style classessome hex addresses have also been shortened to protect the sighted)from decorator import spam spam( call to spam really calls the tracer wrapper object spam(' '' '' 'call to spam abc invokes __call__ in class spam calls number calls in wrapper state information spam when runthe tracer class saves away the decorated functionand intercepts later calls to itin order to add layer of logic that counts and prints each call notice how the total number of calls shows up as an attribute of the decorated function--spam is really an instance of the tracer class when decorateda finding that may have ramifications for programs that do type checkingbut is generally benign (decorators might copy the original function' __name__but such forgery is limitedand could lead to confusionfor function callsthe decoration syntax can be more convenient than modifying each call to account for the extra logic leveland it avoids accidentally calling the original function directly consider nondecorator equivalent such as the followingcalls def tracer(func*args)global calls calls + print('call % to % (callsfunc __name__)func(*argsdef spam(abc)print(abcspam( normal nontraced callaccidentaltracer(spam call to spam special traced call without decorators this alternative can be used on any function without the special syntaxbut unlike the decorator versionit requires extra syntax at every place where the function is called in your code furthermoreits intent may not be as obviousand it does not ensure that the extra layer will be invoked for normal calls although decorators are never required (we can always rebind names manually)they are often the most convenient and uniform option decorators