装饰器
装饰器
例子
def w1(func):
def inner():
print("---正在验证权限---")
if False:
func()
else:
print("没有权限")
return inner
#f1 = w1(f1)
@w1
def f1():
print("---f1---")
@w1
def f2():
print("---f1---")
f1()
f2()
以上例子中,@w1就是语法糖,等价于f1 = w1(f1)
注意,解释器在遇到@w1的时候就已经开始装饰了,不是在调用的时候才进行装饰。后面调用 f1() 函数只是把装饰的结果返回而已。
----------------------------------------------------------------------------------
def w1(func):
def inner():
print("---正在验证权限---")
if False:
func()
else:
print("没有权限")
return inner
def f1():
print("---f1---")
def f2():
print("---f1---")
f1 = w1(f1)
f1()
f2 = w1(f2)
f2()
这块代码和上面那块等价。
执行过程:
第16行之前:
执行 右半部分 w1(f1) 之后:****
执行左边赋值 f1 = w1(f1)
由于蓝色块的代码内存被占用,无法丢弃,所以当执行f2=w1(f2)的时候,会开辟一片新的蓝色块内存,进行与上述同样的操作
#定义函数:完成包裹数据
def makeBold(fn):
def wrapped():
print("----1----")
return "<b>" + fn() + "</b>"
return wrapped
#定义函数:完成包裹数据
def makeItalic(fn):
def wrapped():
print("----2----")
return "<i>" + fn() + "</i>"
return wrapped
@makeBold # test3 = makeBold(test3)
@makeItalic # test3 = makeItalic(test3)
def test3():
print("----3----")
return "hello world-3"
ret = test3()
print(ret)
执行结果与调用过程:
多个装饰器的装饰和解装执行过程:
输出结果是:
通用装饰器:
def func(functionName):
def func_in(*args,**kwargs):
print("----记录日志----")
ret = functionName(*args,**kwargs)
return ret
return func_in
@func
def test(): #对不带参数、有返回值的函数进行装饰
print("----test----")
return "haha"
@func
def test2(): #对不带参数、无返回值的函数进行装饰
print("----test2----")
@func
def test3(a): #对带参数、无返回值的函数进行装饰
print("----test3--a=%d--"%a)
ret = test()
print("test return value is %s"%ret)
a = test2()
print("test2 return value is %s"%a)
test3(11)
带有参数的装饰器:
def func_arg(arg):
def func(functionName):
def func_in():
print("---记录日志-arg=%s---"%arg)
if arg=="heihei":
functionName()
functionName()
else:
functionName()
return func_in
return fun
#1. 先执行func_arg("heihei")函数,这个函数return 的结果是func这个函数的引用
#2. @func
#3. 使用@func对test进行装饰
@func_arg("heihei")
def test():
print("---test---")
#带有参数的装饰器,能够起到在运行时,有不同的功能
@func_arg("haha")
def test2():
print("---test2---")
test()
test2()
类装饰器:
class Test(object):
def __init__(self,func):
print("---初始化---")
print("func name is %s"%func.__name__)
self.__func = func
def __call__(self):
print("---装饰器中的功能---")
self.__func()
@Test
def test():
print("---test---")
# 执行test()
test()
执行过程:
关键点:
- test变量想要调用类,则要在类里面写__call__(self),之后调用变量test()的时候则会调用__call__(self)方法。
-
@Test 在进行装饰的时候就已经调用了__init__()方法了。原因是@Test 等价于 test = Test(test)
函数装饰器和类装饰器的区别:
函数装饰器是:有一个函数A,再定义另外一个新函数B,然后让新函数B里面有一个变量指向函数A,然后让函数A的名字指向新函数B
类装饰器: 让A函数名指向一个对象,这个对象里面有个属性指向原来的函数A