文章目录
第七章 函数装饰器和闭包
闭包除了在装饰器中有用之外,闭包还是回调式异步编程和函数式编程风格的基础。
7.1 装饰器基础知识
装饰器是可调用的对象,其参数是另一个函数。装饰器可能会处理被装饰的函数,然后把它返回,或者将其替换成另一个函数或可调用对象。
def decorate(func):
def inner():
print('running inner()')
return inner
@decorate
def target():
print('running target()')
target()
输出:
装饰器的一大特性是,能把被装饰的函数替换成其他函数。
7.2 Python何时执行装饰器
registry = [] # <1>
def register(func): # <2>
print('running register(%s)' % func) # <3>
registry.append(func) # <4>
return func # <5>
@register # <6>
def f1():
print('running f1()')
@register
def f2():
print('running f2()')
def f3(): # <7>
print('running f3()')
def main(): # <8>
print('running main()')
print('registry ->', registry)
f1()
f2()
f3()
if __name__ == '__main__':
print('aaaaaaaaaa')
main() # <9>
输出:
- registry保存被@registry装饰的函数引用
- registry的参数是一个函数
- 为了演示,显示被装饰的函数
- 把func存入registry
- 返回func:必须返回函数;这里返回的函数与通过参数传入的一样。
- f1和f2被@registry装饰
- f3没有被装饰
- main显示registry,然后调用三个函数
register在其他函数之前运行(两次)。调用register时,传给它的函数是被装饰的函数,例如<function f1 at 0x04B89388>
函数装饰器在导入模块时立即执行,而被装饰的函数只在明确调用时运行。这就是导入时和运行时的区别。
- 装饰器通常在一个模块中定义,然后应用到其他模块中的的函数中。
- 大多数装饰器都会在内部定义一个函数,然后将其返回。
7.3 使用装饰器改进“策略”模式
多数装饰器会修改诶装饰的函数。通常,它们会定义一个内部函数,然后将其返回,替换被装饰的函数。使用内部函数的带啊几乎都要拷闭包才能准确运行。先了解Python中的变量作用域
>>> def f1(a):
... print(a)
... print(b)
...
>>> f1(3)
3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in