def ( )return def ( )return def ( )return @ @ @ def func()print('spam'func(func ( ( (func))prints "spamthe same syntax works on classesas do these same do-nothing decorators when decorators insert wrapper function objectsthoughthey may augment the original function when called--the following concatenates to its result in the decorator layersas it runs the layers from inner to outerdef ( )return lambda'xf(def ( )return lambda'yf(def ( )return lambda'zf(@ @ @ def func()return 'spamprint(func()func ( ( (func))prints "xyzspamwe use lambda functions to implement wrapper layers here (each retains the wrapped function in an enclosing scope)in practicewrappers can take the form of functionscallable classesand more when designed welldecorator nesting allows us to combine augmentation steps in wide variety of ways decorator arguments both function and class decorators can also seem to take argumentsalthough really these arguments are passed to callable that in effect returns the decoratorwhich in turn returns callable by naturethis usually sets up multiple levels of state retention the followingfor instance@decorator(abdef (arg) ( the basics