装饰器也叫语法糖,本质上是一种闭包函数,可以使用@语法加在函数或者类上面,以函数为例,它的作用就是在不修改被装饰函数代码的情况下扩展其功能,符合封闭开放的原则。
它实现的原理是什么呢?其实装饰器就是把被装饰函数当作自己的参数,
在自己内部调用该函数,并加上一些辅助逻辑,
然后再把被当作参数的函数返回给内嵌函数,
再return内嵌函数将新加的功能一起返回给装饰器,
于此同时,底层代码会设置一个与原函数同名的变量取接受装饰器对象的值,
所以我们在调用被装饰函数的时候其实调用的已经不是原函数了,
而是一个挂着原函数名字的新函数
附上参考代码:
def decoration(func):
def wrapper():
print('你已经被我装饰了')
func() #test函数被当作参数传进来了,并在这里调用
return func #将test函数返回
return wrapper #将带有新增功能的函数返回
@decoration #相当于test=decoration
def test():
print('我是一个函数')
test() #这里调用test其实是调用decoration了
结果
你已经被我装饰了
我是一个函数
将到这里相信大家应该能装饰器是怎么运作的了,接下来就贴几段常用的装饰器代码供大家理解和参考
1,加参数的装饰器
def decoration(func):
def wrapper(*args,**kwargs): #无论几个参数,我都能接
print('你已经被我装饰了')
func(*args,**kwargs) #直接到原函数就行了可
return func
return wrapper
@decoration
def test(num):
print('我是%s个函数'%num)
这是加参数的装饰器的写法
2,装饰类的装饰器
def decoration(cls):
def wrapper(*args,**kwargs):
print('你已经被我装饰了')
mycls = cls(*args,**kwargs)
return mycls
return wrapper
@decoration
class Name(object):
def __init__(self,age):
self.age = age
def func(self):
print(self.age)
name = Name(18)
name.func()
嗯嗯,感觉已经无敌了
3,多层装饰器
我之前在网上看到一个很绕的装饰器,看起来很牛的样子,其实平常并用的不多,但是对于我们理解装饰器还是比较用帮助的,因为我觉得他们都没有解释的很清楚这个多层装饰器,所以我copy过来用自己的话解释一下
def A(funC): #给个A装饰器,func是传入的被装饰的函数,也就是C函数
def decorated_C(funE): #funE传入的是c所需要的参数,也就是E函数
def decorated_E_by_CA(*args, **kwargs): #多加一层内嵌函数,准备需要传参的情况
#这一句可以看成out = C(E)(str),C(E)就是被C装饰器装饰过的E函数,E(str)=C(E)(str),理解了这句话那么这个多层装饰器也就理解通了
out = funC(funE)(*args, **kwargs)
return out +' > decorated by A'
return decorated_E_by_CA
return decorated_C
@A
def C(funE):
def decorated_E_by_C(str):
return funE(str)+' > decorated by C'
return decorated_E_by_C
@C #被C装饰后,E函数已经不是原来的那个E了,而是E=C(E)
def E(str):
return str
那么就是这样了
它还有个变形写法
def A(funE_decorated_by_C): #funE_decorated_by_C就是E
def redecorated_E(str): #str就是E(str)调用的参数
return funE_decorated_by_C(str)+' > redecorated by A'
return redecorated_E
def C(funE): #E函数被C装饰后,E=C(E)
def decorated_E(str):
return funE(str)+' > decorated by C'
return decorated_E
@A
@C
def E(str):
return str
print E('A string is ')
好了,大家尽力理解