5.3. DecoratorsDue to the existence of descriptor types such as staticmethod and classmethod, covered in "Class-Level Methods" on page 99, which take as their argument a function object, Python somewhat frequently uses, within class bodies, idioms such as: def f(cls,...): ...definition of f snipped... f = classmethod(f) Having the call to classmethod occur textually after the def statement may decrease code readability because, while reading f's definition, the reader of the code is not yet aware that f is destined to become a class method rather than an ordinary instance method. The code would be more readable if the mention of classmethod could be placed right before, rather than after, the def. Python 2.4 allows such placement, through the new syntax form known as decoration: @classmethod def f(cls,...): ...definition of f snipped... The @classmethod decoration must be immediately followed by a def statement and means that f=classmethod(f) executes right after the def statement (for whatever name f the def defines). More generally, @expression evaluates the expression (which must be a name, possibly qualified, or a call) and binds the result to an internal temporary name (say, _ _aux); any such decoration must be immediately followed by a def statement and means that f=_ _aux(f) executes right after the def statement (for whatever name f the def defines). The object bound to _ _aux is known as a decorator, and it's said to decorate function f. Decoration affords a handy shorthand for some higher-order functions (and other callables that work similarly to higher-order functions). You may apply decoration to any def statement, not just to def statements occurring in class bodies. You may also code custom decorators, which are just higher-order functions, accepting a function object as an argument and returning a function object as the result. For example, here is a decorator that does not modify the function it decorates, but rather emits the function's docstring to standard output at function-definition time: def showdoc(f): if f._ _doc_ _: print '%s: %s' % (f._ _name_ _, f._ _doc_ _) else: print '%s: No docstring!' % f._ _name_ _ return f @showdoc def f1( ): "a docstring" # emits: f1: a docstring @showdoc def f2( ): pass # emits: f2: No docstring! ![]() |