0%

Python - 装饰器

1. 装饰器的概念

装饰器(decorator):
装饰器是一种闭包的使用,要理解装饰器的原理必须先理解python闭包的概念。

关于闭包的知识可以参考>>传送门 - Python闭包<<

2. 举例理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# -*- coding: utf-8 -*-

def deco(func):
print("deco")
def inner_deco(*args): # 调用的enclosing作用域中的对象,inner_deco函数就是个闭包
print("inner_deco")
for a in args:
if not isinstance(a, int): # 参数检查语句
return 0
return func(*args) # 调用了enclosing作用域的func,所以func会被加入到inner_deco的__closure__属性中
return inner_deco

@deco # 语法糖,就相当于func_sum = deco(func_sum),此时func_sum就指向了inner_deco。可以理解为func_sum被deco装饰后变成了inner_deco
def func_sum(*args):
print("func_sum")
return sum(args)

@deco
def func_min(*args):
print("func_min")
return min(args)

# func_sum = deco(func_sum)
print(func_sum(1,2,'3'))

print(func_min(4,5,6))
1
2
3
4
5
6
7
8
运行结果:
deco
deco
inner_deco
0
inner_deco
func_min
4

@deco只是一种语法糖写法
之所以打印结果中没有输出:”func_sum”,是因为在执行参数检查语句时return 0了。

3. 知识点

3.1 装饰器在何时生效?

在main函数之前,import时就生效了。因为@deco就相当于func_sum = deco(func_sum),是写在最外面的。
如果把上述例子中最后的两个print语句注释掉的话,执行结果将会是:

1
2
deco
deco

3.2 装饰器能不能返回别的函数?

当然可以,这样就可以修改函数的功能了。
即被装饰的函数的功能取决于inner_deco返回的是哪个函数。