Function decorators let us "mark" functions in the source code to enhance their behavior in some way. This is powful stuff, but mastering it requires understanding closures.
Aside from their appliation in decorators, closures are also essential for effective asynchronous programming with callbacks, and for coding in a functional style whenever it makes sense.
1. Decorators 101
Example 7-1. A decorator usually replaces a function with a different one
""" A decorator is a callable that takes another function as argument(the decorated function). The decorator may perform some processing with the decorated function, and returns it or replaces it with another function or callable object. """ """ Assuming an existing decorator named decorate, this code: @decorate def target(): print(‘running target()‘) Has the same effect as writing this: def target(): print(‘running target()‘) target = decorate(target) The end result is the same: at the end of either of these snippets, the target name does not necessarily refer to the original target function, but to whatever function is returned by decorate(target). """ # This example show that the decorated function is replaced. >>> def deco(func): ... def inner(): ... print("running inner()") ... return inner ... >>> @deco ... def target(): ... print(‘running target()‘) ... >>> target() # Invoking the decorated target actually runs inner. running inner() >>> target # target is a new reference to inner. <function deco.<locals>.inner at 0x1036259d8> """ Strictly speaking, decorators are just syntactic sugar. As we just saw, you can always simply call a decorator like any regular callable, passing another functions. Sometimes that is actually convenient, especially when doing metaprogramming --- changing program behavior at runtime. """
To Summarize:
# the first crucial fact about decorators is that they have the power to replace the decorated function with a different one. # the second crucial fact is that they are executed immediately when a module is loaded.
2. When Python Execute Decorators
A key feature of decorators is that they run right after the decorated function is defined. This is usually at import time. (i.e., when a module is loaded by Python).
Example 7-2. The ex7_2_registration.py module
registry = [] def register(func): print(‘running register(%s)‘ % func) registry.append(func) return func # Return func: we must return a function; here we return the same received as argument. @register def f1(): print(‘running f1()‘) @register def f2(): print(‘running f2()‘) def f3(): print(‘running f3()‘) def main(): print(‘running main()‘) print(‘registry-->‘, registry) f1() f2() f3() if __name__ == ‘__main__‘: main() # main() is only invoked if ex7_2_registration.py runs as a script. # The output of running ex7_2_registration.py as a script looks like this: """ NEO:ch7-function-decorators-closures zhenxink$ python3 ex7_2_registration.py running register(<function f1 at 0x103e61488>) running register(<function f2 at 0x103e61598>) running main() registry--> [<function f1 at 0x103e61488>, <function f2 at 0x103e61598>] running f1() running f2() running f3() """ """ register runs (twice) before any other function in the module. When register is called, it receives as an argument the function object being decorated -- for example, <function f1 at 0x103e61488> . After the module is loaded, the registry holds references to the two decorated functions: f1 and f2. These functions, as well as f3, are only executed when explicitly called by main. """ # If ex7_2_registration.py is imported(and not run as a script), the output is this: """ >>> import ex7_2_registration running register(<function f1 at 0x1035619d8>) running register(<function f2 at 0x103561a60>) >>> ex7_2_registration.registry [<function f1 at 0x1035619d8>, <function f2 at 0x103561a60>] """ """ The main point of Example 7-2 is to emphasize that function decorators are executed as soon as the module is imported, but the decorated functions only run when they are explicitly invoked. This highlights the difference between import time and runtime. (导入时 和 运行时) """ # Considering how decorators are commonly employed in real code, Example 7-2 is unusual in two ways: """ 1. The decorator function is defined in the same module as the decorated functions. A real decorator is usually defined in one module and applied to functions in other modules. 2. The register decorator returns the same function passed as argument. In practice, most decorators define as inner function and return it. """ """ Even though the register decorator in Example 7-2 returns the decorated function unchanged, that technique is not useless. Similar decorators are used in many Python web frameworks to add functions to some central registry -- for example, a registry mapping URL patterns to functions that generate HTTP response. Such registration decorators may or may not change the decorated function. """
end ...
原文地址:https://www.cnblogs.com/neozheng/p/12254440.html