刚学flask,对形如@func的装饰器一直不太理解,今天花了一天时间学了一下。下面简单谈下自己的粗浅的理解
装饰器
什么是装饰器,知乎上【文献1】的理解比较生动,意思就是本来函数func是实现功能A,现在要给它附加一个功能B,但是又不想重写代码,于是给它包装了一个函数,在该函数内实现了B功能。这样做提高的代码的复用率,减小了重复编写。
举个例子,假设原来的函数是f1,实现了一个功能A:print(‘A’)
def f1()
print('A') #执行功能A
现在有一个新的需求,需要添加功能B,我们可以在函数外面再套一个函数,写成如下的形式:
def f2(f1):
f1() #执行功能A
print('B') #执行功能B
这里f1作为参数传入。现在每次实现这个功能的时候,我们都要写成f2(f1),那么有没有更简便的写法呢?
def f2(func):
def wrapper(*args,**kwargs):
print('B') #执行功能B
return func(*args,**kwargs)
return wrapper
def f1():
print('A') #执行功能A
f1=f2(f1)
f1()#如果没有这一步,该程序不会返回任何值
最后的f1=f2(f1),相当于将f1重新改写了,此时的f1函数,就相当于执行了功能A和功能B的f2函数,只是用更简单的形式,代替了原有写法。为了简化这一步骤,有了‘@’这种写法。
@符号是装饰器的语法糖(指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会),在定义函数的时候使用,避免再一次赋值操作。
@f2
def f1():
print("A")
这句就相当于f1=f2(f1) (函数运行的时候,需要调用f1());以后每次调用f1都会执行f2(f1),此时的f1不再是原来的f1函数了,而是增加了功能B的f1,虽然名字没变,但是如同加了一层装饰。
注意:
在f2中如果没有def wrapper这一步,而直接写成下列形式:
def f2(func):
print('B') #执行功能B
func()
return func
@f2
def f1():
print('A') #执行功能A
计算结果如下
B
A
此时,对原有函数进行改动
def f2(func):
print('B') #执行功能B
func()
return func
@f2
def f1():
print('A') #执行功能A
f1()
运行结果为
B
A
A
也就是说,结果f1的函数内容并没有改变;
参考文献
1、如何理解Python装饰器
2、Python装饰器学习(九步入门):通过九种例子,加深对装饰器的理解,但是这九个例子一定要在自己程序上跑一跑,原文给出的解释有的地方是有问题的,参考评论区的意见。
3、Python 装饰器:这篇博文也是通过例子,讲装饰器,可以看做上面的补充。
注释
1、语法糖百度百科