文章目录
装饰器的简单使用
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
func(*args, **kwargs) #此处拿到了被装饰的函数func
time.sleep(2)#模拟耗时操作
long = time.time() - start
print(f'共耗时{long}秒。')
return wrapper #返回内层函数的引用
@timer
def add(a, b):
print(a+b)
add(1, 2) #正常调用add
上述代码中 timer被我们改造成了装饰器,它接受被装饰函数
为入参,返回内部嵌套函数的引用
(注意:此处并未执行函数),内部嵌套函数wrapper持有被装饰函数的引用即 func
。
“@”是Python的语法糖,它的作用类似于:
add = timer(add) #此处返回的是timer.<locals>.wrapper函数引用
add(1, 2)
装饰器对于原函数的影响
为了消除装饰器对原函数的影响,我们需要伪装成原函数,拥有原函数的属性,看起来就像是同一个人一样。
functools为我们提供了便捷的方式,只需这样:
def auth(permission):
def _auth(func):
@functools.wraps(func) # 注意此处
def wrapper(*args, **kwargs):
print(f"验证权限[{permission}]...")
func(*args, **kwargs)
print("执行完毕...")
return wrapper
return _auth
@auth("add")
def add(a, b):
"""
求和运算
"""
print(a + b)
print(add)
print(add.__name__)
print(add.__doc__)
输出:
<function add at 0x10997c488>
add
求和运算
functools.wraps对我们的装饰器函数进行了装饰之后,add表面上看起来还是add。
functools.wraps内部通过partial和update_wrapper对函数进行再加工,将原始被装饰函数(add)的属性拷贝给装饰器函数(wrapper)。