关于python 装饰器
关于装饰器
无参装饰器
普通函数
def say_hello(*args, **kwargs):
print 'hello world'
无参装饰器
def debug(func): # debug为装饰器,func为要被装饰的函数
def wrapper(*args, **kwargs):
# 此处的args,kwargs承接func函数的参数,使用wrapper替换func
# 装饰器最内层的函数为被装饰函数的替换函数,参数列表必须和被装饰函数相同
print "[DEBUG]: enter {}()".format(func.__name__)
return func(*args, **kwargs) # 调用被装饰的func函数
return wrapper
装饰器调用,原始方法
say_hello = debug(say_hello) # 添加功能并保持原函数名不变
等价于 语法糖 方式调用
@debug
def say_hello():
print "hello!"
对于有参装饰器
def debug(flag):
# 通过语法糖方式 @debug(flag=True)调用后才获取到了wrapper函数,然后才是使用wrapper再次装饰(无参形式)func函数
def wrapper(func):
def inner(*args,**kwargs):
print "[DEBUG]: enter {}()".format(func.__name__)
return func(*args, **kwargs)
return inner
return wrapper
语法糖 方式调用
@debug(flag=True)
def say_hello():
print "hello!"
等价于
wrapper = debug(flag=True) # wrapper 是一个函数
say_hello = wrapper(say_hello) # wrapper相当 debug(say_hello)的功能
类方法的函数装饰器
类方法的函数装饰器和函数的函数装饰器类似
对于类方法来说,都会有一个默认的参数self,它实际表示的是类的一个实例,所以在装饰器的内部函数inner也要传入一个类实例的参数,其他的用法都和函数装饰器相同。
如:
def debug(flag):
def wrapper(func):
def inner(instance, *args, **kwargs): # 类方法的函数装饰器的装饰函数参数列表必须和被装饰的函数一样,故第一个参数必须为等同于类方法的self的类实例
print "[DEBUG]: enter {}()".format(func.__name__)
return func(instance, *args, **kwargs)
return inner
return wrapper
装饰:
class Method(object):
@debug(flag=False)
def func(self, args, kwargs):
time.sleep(0.8)
functools.wraps()函数
打印装饰后的 say_hello
函数的 __name__
print(say_hello.__name__)
输出: inner
造成被装饰函数自身的信息丢失,可以使用functools.wraps()解决该问题
from functools import wraps
def debug(flag):
def wrapper(func):
@wraps(func)
def inner( *args, **kwargs):
print "[DEBUG]: enter {}()".format(func.__name__)
return func(*args, **kwargs)
return inner
return wrapper
print(say_hello.__name__)
输出: say_hello
装饰器调用顺序
无参装饰器
def dec1(func):
print "AAAAA"
def inner(*args, **kwargs):
print "BBBBB"
func(*args, **kwargs)
return inner
def dec2(func):
print "CCCCC"
def inner(*args, **kwargs):
print "DDDDD"
func(*args, **kwargs)
return inner
@dec1
@dec2
def test():
pass
test()
输出为:
CCCCC
AAAAA
BBBBB
DDDDD
因为等价于
test = dec2(test) # 输出 CCCCC
test = dec1(test) # 输出 AAAAA
test() # 输出BBBBB DDDDD
带参装饰器
def dec1(*args):
print "11111"
def wrapper(func):
print "AAAAA"
def inner(*args, **kwargs):
print "BBBBB"
func(*args, **kwargs)
return inner
return wrapper
def dec2(*args):
print "22222"
def wrapper(func):
print "CCCCC"
def inner(*args, **kwargs):
print "DDDDD"
func(*args, **kwargs)
return inner
return wrapper
@dec1()
@dec2()
def test():
pass
test()
输出为:
11111
22222
CCCCC
AAAAA
BBBBBB
DDDDD
因为等价于
wrapper1 = dec1() # 输出 11111
wrapper2 = dec2() # 输出 22222
# 类似无参的情况
@wrapper1
@wrapper2
def test():
pass
test() # 输出 CCCCC AAAAA BBBBBB DDDDD
还没有评论,来说两句吧...