10 带参数的装饰器 通用装饰器 类装饰器
版本1)不带参数的闭包
def timefun(func): print('---fun1--') def time_in(): print("--time_in is 1") func() print('---time_in is 2') print('---fun2--') return time_in def f1(): print("this is f1") f1 = timefun(f1) f1()
---fun1-- ---fun2-- --time_in is 1 this is f1 ---time_in is 2
版本2)不带参数函数的被装饰
def timefun(func): print('---fun1--') def time_in(): print("--time_in is 1") func() print('---time_in is 2') print('---fun2--') return time_in @timefun def f1(): print("this is f1") f1()
版本3)带参数函数的被装饰
def timefun(func): print('---fun1--') def time_in(num1,num2): print("--time_in is 1") func(num1,num2) print('---time_in is 2') print('---fun2--') return time_in @timefun def f1(a,b): print('--f1:a=%d,b=%d'%(a,b)) f1(1,2)
版本4)不定长参数函数被装饰
def timefun(func): print('---装饰用的1--') def time_in(*args,**kwargs): print("--time_in is 1") func(*args,**kwargs) print('---time_in is 2') print('---fun2--') return time_in @timefun def f1(a,b): print('--f1:a=%d,b=%d'%(a,b)) @timefun def f2(a,b,c,d): print('--f2:a=%d,b=%d,c=%d,d=%d'%(a,b,c,d)) f1(1,2) f2(1,2,3,4)
5 带返回值的函数 被装饰
1)带返回值的函数
def test(): print('----test--') return "haha" ret = test() print("test return ---%s"%ret) ## 运行结果 ----test-- test return ---haha
2)带返回值的装饰器
def fun(func): def time_in(): func() return time_in @fun def test(): print('----test--') return "haha" ret = test() print("test return ---%s"%ret) ### 运行结果 ----test-- test return ---None
3)带返回值的函数 被装饰
def fun(func): def time_in(): ret = func() #保存返回来的haha return ret #把haha返回到最后17行的调用 return time_in @fun def test(): print('----test--') return "haha" ret = test() print("test return ---%s"%ret)
6.通用装饰器
def func(func): def fun_in(*args,**kwargs): print('--记录日志--') re = func(*args,**kwargs) return re return fun_in @func def test1(): print('--test1') return "haha" @func def test2(): print('--test2--a=%d') @func def test3(a): print('--test3--a=%d'%a) ret = test1() print('test return :%s'%ret) ret2 = test2() print('test2 return :%s'%ret2) test3(11)
--记录日志-- --test1 test return :haha --记录日志-- --test2--a=%d test2 return :None --记录日志-- --test3--a=11
7.装饰器带参数,
在原有装饰器的基础上,设置外部变量,执行一次函数,获取它的返回值而已
def func_arg(arg): def func(functionName): def func_in(): print("---记录日志-%s-"%arg) functionName() return func_in return func #1.先执行func_arg("heihei")函数,这个函数return 的结果是func这个函数的引用 #2.@func #3.使用@func对test进行装饰 @func_arg('heihei') def test1(): print('---testt') test1()
---记录日志-heihei- ---testt
2)有什么用
def func_arg(arg): def func(functionName): def func_in(): print("---记录日志-%s-"%arg) if arg == "alex": functionName() functionName() else: functionName() return func_in return func #1.先执行func_arg("heihei")函数,这个函数return 的结果是func这个函数的引用 #2.@func #3.使用@func对test进行装饰 @func_arg('heihei') def test1(): print('---testt') #带有参数的装饰器,能够起到在运行时,有不同的功能 @func_arg('alex') def test2(): print('---alex') test1() test2()
---记录日志-heihei- ---testt ---记录日志-alex- ---alex ---alex
8.类装饰器__call__
1 __call__方法
装饰器函数其实是这样一个接口约束,它必须接受一个callable对象作为参数,然后返回一个callable对象。在Python中一般callable对象都是函数,但也有例外。只要某个对象重写了 __call__()
方法,那么这个对象就是callable的。
In [18]: class Dog(object): ....: def __call__(self): ....: print("---test-") ....: In [19]: d = Dog() In [20]: d() ---test-
2)类装饰器
class Test(object): def __init__(self, func): print("---初始化---") print("func name is %s"%func.__name__) self.__func = func def __call__(self): print("---装饰器中的功能---") self.__func() #说明: #1. 当用Test来装作装饰器对test函数进行装饰的时候,首先会创建Test的实例对象 # 并且会把test这个函数名当做参数传递到__init__方法中 # 即在__init__方法中的func变量指向了test函数体 # #2. test函数相当于指向了用Test创建出来的实例对象 # #3. 当在使用test()进行调用时,就相当于让这个对象(),因此会调用这个对象的__call__方法 # #4. 为了能够在__call__方法中调用原来test指向的函数体,所以在__init__方法中就需要一个实例属性来保存这个函数体的引用 # 所以才有了self.__func = func这句代码,从而在调用__call__方法中能够调用到test之前的函数体 @Test def test(): print("----test---") test() showpy()#如果把这句话注释,重新运行程序,依然会看到"--初始化--"
运行结果如下: ---初始化--- func name is test ---装饰器中的功能--- ----test---