Python Syntax and Semantics - Decorators

Decorators

A decorator is any callable Python object that is used to modify a function, method or class definition. A decorator is passed the original object being defined and returns a modified object, which is then bound to the name in the definition. Python decorators were inspired in part by Java annotations, and have a similar syntax; the decorator syntax is pure syntactic sugar, using @ as the keyword:

@viking_chorus def menu_item: print("spam")

is equivalent to

def menu_item: print("spam") menu_item = viking_chorus(menu_item)

Decorators are a form of metaprogramming; they enhance the action of the function or method they decorate. For example, in the above sample, viking_chorus might cause menu_item to be run 8 times (see Spam sketch) for each time it is called:

def viking_chorus(myfunc): def inner_func(*args, **kwargs): for i in range(8): myfunc(*args, **kwargs) return inner_func

Canonical uses of function decorators are for creating class methods or static methods, adding function attributes, tracing, setting pre- and postconditions, and synchronisation, but can be used for far more besides, including tail recursion elimination, memoization and even improving the writing of decorators.

Decorators can be chained by placing several on adjacent lines:

@invincible @favorite_color("Blue") def black_knight: pass

is equivalent to

def black_knight: pass black_knight = invincible(favorite_color("Blue")(black_knight))

or, using intermediate variables

def black_knight: pass blue_decorator = favorite_color("Blue") decorated_by_blue = blue_decorator(black_knight) black_knight = invincible(decorated_by_blue)

In the above example, the favorite_color decorator factory takes an argument. Decorator factories must return a decorator, which is then called with the object to be decorated as its argument:

def favorite_color(color): def decorator(func): def wrapper: print(color) func return wrapper return decorator

This would then decorate the black_knight function such that the color, "Blue", would be printed prior to the black_knight function running.

In Python prior to version 2.6, decorators apply to functions and methods, but not to classes. Decorating a (dummy) __new__ method can modify a class, however. Class decorators are supported starting with Python 2.6.

Despite the name, Python decorators are not an implementation of the decorator pattern. The decorator pattern is a design pattern used in statically typed object-oriented programming languages to allow functionality to be added to objects at run time; Python decorators add functionality to functions and methods at definition time, and thus are a higher-level construct than decorator-pattern classes. The decorator pattern itself is trivially implementable in Python, because the language is duck typed, and so is not usually considered as such.

See also
Advice in Lisp.

Read more about this topic:  Python Syntax And Semantics