好多年一直没学特别明白的知识始终缠绕着我。打算先写简单一点。
装饰器的目的是在不改变函数本身的前提下,为函数增添新的功能。
# 简单的例子
比如,下面是一个简单的函数,用来输出一个字符串 run func1 :
def func1(): | |
print("run func1") | |
func1() |
如果希望对其进行修改,使其先输出 program start , 再输出 run func1 ,那么就需要对 func1 进行修改,也就是
def func1(): | |
print("program start") | |
print("run func1") | |
func1() |
但是这样修改了函数本身。如果不修改,简单的方式是新定义一个函数,即
def func1(): | |
print("run func1") | |
def prog1(func): | |
print("program start") | |
func() | |
prog1(func1) |
如果我们想要在调用原有函数 func1 的情况下,同时不改变 func1 本身,那么就需要再调用一次。比如:
def func1(): | |
print("run func1") | |
def prog1(func): | |
print("program start") | |
func() | |
func1 = prog1(func1) | |
func1() |
但是这里会出现报错,因为 prog1 的返回是空值,因此不能作为 func1 被赋予的值。于是需要再嵌套一层包裹函数:
def func1(): | |
print("run func1") | |
def prog1(func): | |
def warpper(): | |
print("program start") | |
func() | |
retturn warpper | |
func1 = prog1(func1) | |
func1() |
但是这样写 func1 = prog1(func1) 比较难懂,所以就使用了一个语法糖 @ , 变成:
def prog1(func): | |
def wrapper(): | |
print("program start") | |
func() | |
return wrapper | |
@prog1 | |
def func1(): | |
print("run func1") | |
func1() |
嗯,这就是装饰器。
总的来说,如果要写一个装饰器,需要包括两部分:
- 装饰器函数,也就是
prog1, 其包含了需要对被装饰函数所新增的内容。 - 被装饰函数,也就是
func1, 这里需要在其之前写@prog1表明该函数使用了装饰器prog1.
# References
- Python 的高阶玩法:装饰器(没人比我讲的更简单易懂了吧) - jasonj333 的文章 - 知乎