就是把自己定义的函数装饰一遍,在原来函数的基础上做些其他操作,然后返回一个新的函数,调用名称是一样的,只是内容稍有变化(注意是新的,已经不是本来定义的函数了,但是原来的函数最终还是会在装饰器最内层返回的,只是返回时添加了些东西,比如逻辑判断,打印,往哪个列表添加东西等等操作,比如在原来函数功能的基础上,判断是否登录,是否是VIp,再执行该函数)
装饰函数无参数
可以看出调用decorator函数,返回的是wrapper函数对象,而不是abc这个函数对象,
abc这个函数在wrapper中已经是被调用了的,只是返回一个结果。以上代码的运行结果如下图,可以看出装饰
#装饰函数无参数
def decorator(foo):
def wrapper():
print('wrapper')
return foo()
return wrapper
#自定义函数
def abc():
print ('abc')
#装饰函数abc,使之函数abc()运行时,提前print('wrapper')
abc = decorator(abc) # abc = wrapper
abc() # wrapper abc
print(abc()) # wrapper abc None
python的装饰器语法就是自动调用decorator函数,并以自定义的函数abc函数对象为参数,返回wrapper函数对象,这样一个过程。
切记 : 回调函数不可以使用装饰器,如果非要使用那就把这个回调函数名再赋值一个新名字,用新名字的函数去装饰
def decorator(foo):
def wrapper():
print ('@wrapper')
return foo()
return wrapper
@decorator # @相当于abc = decorator(abc),只是他在定义定义其他函数时就把那个函数装饰了,把函数名作为装饰器的参数
def abc():
print ('abc')
abc() # @wrapper abc
print(abc()) # @wrapper abc None
带参数的装饰器:
接下来,再深一步来说说带参数的装饰器, 其实这个只比上面那个无参数装饰器多了一步,就是先调用装饰器函数,再返回真正的装饰器,之后的步骤和无参数的一样了,说得太抽象?
直接上代码,这样就明显了,先调用用最外层的函数,返回的是一个真正的装饰器,然后像之前无参数的时候一样,修饰abc函数后返回新的函数对象
def decoratorFunc(arg):
def decorator(foo):
def wrapper():
if arg == 0:
print('lalala')
return foo()
return wrapper
return decorator
deco0 = decoratorFunc(0) # deco0 = decorator 带有暂时不用的参数0 return decorator
deco1 = decoratorFunc(1) # deco1 = decorator 带有暂时不用的参数1 return decorator
def abc():
print('abc')
abc0 = deco0(abc) # abc0 = decorator(abc) return wrapper
abc1 = deco1(abc) # abc1 = decorator(abc) return wrapper
abc0() #lalala abc
abc1() # abc
@decoratorFunc(0)
def abc():
print ('abc')
abc1() # abc
输出:
lalala
abc
abc
abc
写更普通的装饰器,如果被装饰的函数有参数怎么办?很简单,利用python的可变长度参数就行。
注意,是在wrapper这个函数上我们写上python的可变长度参数,而装饰器函数decorator的参数永远只有一个,就是函数对象。看以下代码,是无参数装饰器的例子,
如果是带参数的函数,也只需要把wrapper改成接收可变长度参数就行
def decorator(foo):
def wrapper(*args, **kwargs):
print ('wrapper')
return foo(*args, **kwargs)
return wrapper
@decorator
def abc(arg):
print ('abc:', arg)
abc('你好啊') #wrapper abc: 你好啊