1. 不带参数的装饰器 调用G() 等价于 G = E(G)
def E(func): def F(): print('这里时F函数里面') return func() return F @E def G(): print('执行了G函数') G()
2. 带参数的装饰器 ,其实就是最外层给传递参数用,里面还是一个闭包
调用C() 等价于 C = A(text) (C)
def A(text): def B(func): def wrapped(): print('text 参数 = %s'%text) return func() return wrapped return B @A('我如黎明中的花朵') def C(): print('执行了C函数') C()
3. 装饰有返回值的函数
def N(functionname): print('---N----') def func_in(): print('---func_in---1---') ret = functionname() print('---func_in---2---') return ret print('---func---2---') return func_in @N def M(): print('---test---') return '哈哈' ret = M() print('test return value is %s'%ret)
为什么打印信息是这样? 解释器遇到@N , 就等同于遇到了M = N (M) , 先执行右边的, 顺着 N 函数执行, 返回 的是 func_in 函数的引用, 此时func_in 并没有()
---N----
---func---2---
---func_in---1---
---test---
---func_in---2---
test return value is 哈哈
4. 两个装饰器,@后面必定去寻找函数,没有的话先让下一个装饰器先装饰
def w1(func): print('---正在装饰1 ---') def inner(): print('--- 正在验证权限1 --- ') func() return inner def w2(func): print('---正在装饰2---') def inner(): print('---正在验证权限2---') func() return inner # 只要python解释器执行到了这个代码 那么就会自动进行装饰 而不是等到调用时才装饰的 @w1 @w2 # f1 = w2(f1) def f1(): print('---f1----') f1()
5.类当装饰器
参考:https://blog.csdn.net/yitiaodashu/article/details/79016590
类当作装饰器的意义
如果装饰器想实现的功能比较少,那我们用普通的装饰器即可,但如果我们想实现多种功能,会在一个装饰器里写很多代码,显然用普通的装饰器实现起来很费劲,但如果用类装饰器的话,我们可以把各种功能封装在一个个实例方法中,
然后在__call__方法中调用不同的实例方法。
(1) 不带参数的类装饰器
class Test(object):
def __init__(self, func):
print('---初始化---')
print('func name is %s' % func.__name__)
self.__func = func
def __call__(self, *args, **kwargs):
print('这里写装饰器中的功能代码部分')
self.__func()
@Test #py解释器执行到这儿的时候 会执行test = Test(test)
def test():
print('---test---')
test()
# 说明:
# 1. 当用Test来作装饰器对test函数进行装饰的时候,首先会创建Test的实例对象并且会把test这个函数名当做参数传递到init方法中即在init方法中的属性__func指向了test指向的函数;
# 2. test指向了用Test创建出来的实例对象;通常来讲,实例对象不能直接() , 但是当类中写了call方法就能()
# 3. 当在使用test()进行调用时,就相当于让这个对象(),因此会调用这个对象的call方法;
# 4. 为了能够在call方法中调用原来test指向的函数体,所以在init方法中就需要一个实例属性来保存这个函数体的引用所以才有了self.func = func这句代码,从而在调用__call方法中能够调用到test之前的函数体。
(2) 带参数的类装饰器
class Log(object):
def __init__(self, num):
self.num = num
def __call__(self, func):
self.func = func
return self.call_func
def call_func(self, *args, **kwargs):
print(self.num)
return self.func(*args, **kwargs)
@Log(666)
def test2():
print('你为何如此优秀')
test2()