装饰器(Decorators)是 Python 的一个重要部分。所谓的装饰器,就是修改其他函数的功能的函数,使用装饰器可以在不改变原函数的基础上扩充原函数功能。
函数也是对象
在 Python 中,函数是头等公民(First-class Citizen),其本身是一个对象,这意味着:
- 可以把函数赋予变量;
- 可以在函数内部定义函数(函数嵌套);
- 函数可以作为其他函数的参数传递;
- 函数的返回值也可以是函数对象(闭包)。
示例:函数的嵌套与闭包
|  | def outer_func():
 name = "I'm closure"
 
 
 def inner_func(msg):
 print(f'{msg}{name}')
 
 return inner_func
 
 
 closure = outer_func()
 closure('Hello, ')
 
 | 
函数装饰器
示例一:函数装饰器
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | def decorator(func):def wrapper(*args, **kwargs):
 print('wrapper of decorator')
 func(*args, **kwargs)
 
 return wrapper
 
 
 @decorator
 def greet(msg):
 print(f'{msg}, world')
 
 
 greet('hello')
 greet('goodbye')
 
 | 
示例二:带参数的装饰器
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | def repeat(num):def decorator(func):
 def wrapper(*args, **kwargs):
 for i in range(num):
 print('wrapper of decorator')
 func(*args, **kwargs)
 
 return wrapper
 
 return decorator
 
 
 @repeat(3)
 def greet(msg):
 print(msg)
 
 
 greet('hello world')
 
 | 
示例三:装饰器的嵌套
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 
 | """Python也支持多个装饰器,比如写成下面这样的形式,它的执行顺序从上到下:
 @decorator1
 @decorator2
 @decorator3def func():
 ...
 上面的语句等同于下面这行代码:
 func = decorator1(decorator2(decorator3(func)))
 """
 
 
 def decorator1(func):
 def wrapper(*args, **kwargs):
 print('call decorator1')
 func(*args, **kwargs)
 
 return wrapper
 
 
 def decorator2(func):
 def wrapper(*args, **kwargs):
 print('call decorator2')
 func(*args, **kwargs)
 
 return wrapper
 
 
 @decorator1
 @decorator2
 def greet(message):
 print(message)
 
 
 greet('hello world')
 
 | 
示例四:保留原函数的元信息
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 
 | def decorator(func):
 def wrapper(*args, **kwargs):
 print('wrapper of decorator')
 func(*args, **kwargs)
 
 return wrapper
 
 
 @decorator
 def greet(msg):
 print(msg)
 
 
 print(greet.__name__)
 help(greet)
 
 ---------
 
 import functools
 
 
 def decorator(func):
 @functools.wraps(func)
 def wrapper(*args, **kwargs):
 print('wrapper of decorator')
 func(*args, **kwargs)
 
 return wrapper
 
 
 @decorator
 def greet(msg):
 print(msg)
 
 
 print(greet.__name__)
 help(greet)
 
 | 
类装饰器
除了函数可以作为装饰器,类也可以作为装饰器。类装饰器主要依赖于 __call__() 函数,每当调用一次类的实例时,__call__() 函数就会被执行一次。
示例:构建类装饰器
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | class Count(object):def __init__(self, func):
 self.func = func
 self.num_calls = 0
 
 def __call__(self, *args, **kwargs):
 self.num_calls += 1
 print(f'num of calls is: {self.num_calls}')
 return self.func(*args, **kwargs)
 
 
 @Count
 def greet():
 print('hello world')
 
 
 for _ in range(3):
 greet()
 
 |