什么是Python装饰器
python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能
一个简单的装饰器
def deco(func):
def wrapper():
func()
return wrapper
@deco
def a():
print("i am a")
###
i am a
一个带参数的装饰器需要一个闭包的函数去包装
def par_deco(par=None):
def deco(func):
print(par)
def wrapper(*args, **kwargs):
func(*args, **kwargs)
return wrapper
return deco
@par_deco(par="i am par")
def a():
print("i am a")
###
i am par
i am a
类里面的方法需要添加装饰器,需要在wrapper方法里面传入self参数,代表这个方法传入的类实例,不然直接在类里面调用方法,会出现没有这个实例的现象,传入的self参数是可以共享self实例里面的所有变量和方法的
def skip_a(msg=None):
def runFunc(func):
print("i am " + msg)
def wrapper(self):
if self.b == 1:
return wrapper
else:
func(self)
return wrapper
print(func.__name__)
return runFunc
class test_a:
def __init__(self):
self.b = 2
@skip_a(msg=2)
def a(self):
print(1)
t = test_a()
t.a()
####
i am msg
runFunc
1
上面这个例子看到我们在使用装饰器的时候,原函数是会损失一些信息的,列如doc,name,这样我们排查问题是不熬排查的,如果写过单元测试的小伙伴使用过unittest的时候,加上此装饰器,unittest会暴露一个找不到测试用例的问题,就是因为运行实例的时候name属性变掉了,那我们这个时候就是要@functools.wraps(func)的帮忙了,他能保证不改变原始方法的属性前提下,运行装饰器
def skip_a(msg=None):
def runFunc(func):
print("i am " + msg)
@functools.wraps(func)
def wrapper(self):
if self.b == 1:
return wrapper
else:
func(self)
return wrapper
print(func.__name__)
return runFunc
class test_a:
def __init__(self):
self.b = 2
@skip_a(msg=2)
def a(self):
print(1)
###
i am msg
a
1