python装饰器

python装饰器就是用于扩展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数。使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。

1
2
3
原函数
def func():
print("hello")

要想扩展一个函数的功能,最简单的方法就是直接修改原函数。

1
2
3
4
def func():
print("before")
print("hello")
print("after")

如果不想修改原函数,还是想增强函数的功能时,可以另外定义一个函数调用原函数。(类似于设计模式中的装饰模式,有组合和代理两种方式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def deco(func):
print("before")
func()
print("after")

def func():
print("hello")

if __name__ == '__main__':
f = func
deco(f)#只有把func()或者f()作为参数执行,新加入功能才会生效
print("f.__name__ is",f.__name__)#f的name就是func()
print()
#func()

但是如果存在很多个类似于func的函数需要相同的扩展,那岂不是要执行deco函数许多次?
下面我们实现一个最简陋的装饰器:

1
2
3
4
5
6
7
8
9
10
def deco(func):
def wrapper(*args, **kwargs):
print("before")
func(*args, **kwargs)
print("after")
return wrapper

@deco
def func():
print("hello")

这里的deco函数就是最原始的装饰器,它的参数是一个函数,然后返回值也是一个函数。其中作为参数的这个函数func()就在返回函数wrapper()的内部执行。然后在函数func()前面加上@deco。
所以这里装饰器就像一个注入符号:有了它,拓展了原来函数的功能既不需要侵入函数内更改代码,也不需要重复执行原函数。
在func函数前还可以使用多个@的方式来执行多个装饰器,多个装饰器的执行顺序就是从最后一个装饰器开始执行到第一个装饰器,在执行函数本身。

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
27
28
29
30
def dec1(func):  
print("1111")
def one():
print("2222")
func()
print("3333")
return one

def dec2(func):
print("aaaa")
def two():
print("bbbb")
func()
print("cccc")
return two

@dec1
@dec2
def test():
print("test test")

test()

aaaa
1111
2222
bbbb
test test
cccc
3333