Expert Python Programming(Third Edition)
上QQ阅读APP看书,第一时间看更新

General syntax and possible implementations

The decorator is generally a named callable object (lambda expressions are not allowed) that accepts a single argument when called (it will be the decorated function) and returns another callable object. Callable is used here instead of a function with premeditation. While decorators are often discussed in the scope of methods and functions, they are not limited to them. In fact, anything that is callable (any object that implements the __call__ method is considered callable) can be used as a decorator, and, often, objects returned by them are not simple functions but are instances of more complex classes that are implementing their own __call__ method.

The decorator syntax is simply a syntactic sugar. Consider the following decorator usage:

@some_decorator 
def decorated_function(): 
    pass

This can always be replaced by an explicit decorator call and function reassignment:

def decorated_function(): 
    pass 
decorated_function = some_decorator(decorated_function) 

However, the latter is less readable and also very hard to understand if multiple decorators are used on a single function.

Decorator does not even need to return a callable!
As a matter of fact, any function can be used as a decorator, because Python does not enforce the return type of decorators. So, using some function as a decorator that accepts a single argument but does not return a callable object, let's say   str, is completely valid in terms of syntax. This will eventually fail if the user tries to call an object that's been decorated this way. This part of the decorator syntax creates a field for some interesting experimentation.