Python之装饰器
一 装饰器
#装饰器: 闭包函数的一种应用,只不过其传递的是函数。装饰器的返回值也是一个函数对象。 #装饰器原则: 1. 不修改被装饰对象的 源代码 2. 不修改被装饰对象的 调用方式 #达到的目标: 在遵循1和2的前提下,为被装饰对象添加新功能

简而言之:@a 就是将 b 传递给 a(),并返回新的 b = a(b)
例:
import time def timer(func): def internal(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) stop_time = time.time() print('run time is {}'.format(stop_time - start_time)) return res return internal @timer # 相当于 test = timer(test) def test(): time.sleep(3) print('Hello World') test() # 结果: ''' Hello World run time is 3.010805606842041 '''
二 装饰器使用
import time def timer(func): def internal(*args,**kwargs): start_time = time.time() res = func() stop_time = time.time() print('run time is {}'.format(stop_time - start_time)) return res return internal @timer def test(): time.sleep(3) print('from test') test()
def auth2(auth_type): def auth(func): def internal(*args, **kwargs): if auth_type == 'file': name = input('username:') pwd = input('password:') if name == 'tom' and pwd == '123': print('Auth Success') res = func(*args, **kwargs) return res else: print('Auth error') elif auth_type == 'sql': print('sql 先停停') return internal return auth @auth2(auth_type='file') def index(): print('Hello') index()
三 wrapper返回的不是原函数的帮助信息
当我们使用了装饰器的时候,虽然没有修改代码本身,但是在运行的时候,比如上面这个例子,运行index其实在运行internal了,如果我们打印my_index的注释信息,会打印internal的注释信息,那么该如何处理?
def deco(func): def wrapper(*args, **kwargs): """世界那么大""" return func(*args, **kwargs) return wrapper @deco def index(): '''Hello World''' print('from index') print(index.__doc__)
""" 世界那么大 #并不是想要的 """
解决方法:
# 方式一 from functools import wraps def deco(func): @wraps(func) def wrapper(*args, **kwargs): """世界那么大""" return func(*args,**kwargs) return wrapper @deco def index(): """Hello World""" print('from index') print(index.__doc__) """ Hello World """ #方式二 def deco(func): def wrapper(*args, **kwargs): """世界那么大""" return func(*args, **kwargs) wrapper.__doc__ = func.__doc__ wrapper.__name__ = func.__name__ return wrapper @deco def index(): '''Hello World''' print('from index') print(index.__doc__)
四. 叠加多个装饰器
加载和执行: 1. 加载顺序(outter函数的调用顺序):自下而上 2. 执行顺序(wrapper函数的执行顺序):自上而下
def outter1(func1): # func1=wrapper2的内存地址 print('加载了outter1') def wrapper1(*args, **kwargs): print('执行了wrapper1') res1 = func1(*args, **kwargs) return res1 return wrapper1 def outter2(func2): # func2=wrapper3的内存地址 print('加载了outter2') def wrapper2(*args, **kwargs): print('执行了wrapper2') res2 = func2(*args, **kwargs) return res2 return wrapper2 def outter3(func3): # func3=最原始的那个index的内存地址 print('加载了outter3') def wrapper3(*args, **kwargs): print('执行了wrapper3') res3 = func3(*args, **kwargs) return res3 return wrapper3 @outter1 # outter1(wrapper2的内存地址)======>index=wrapper1的内存地址 @outter2 # outter2(wrapper3的内存地址)======>wrapper2的内存地址 @outter3 # outter3(最原始的那个index的内存地址)===>wrapper3的内存地址 def index(): print('from index') print('=======================') index() """ 加载了outter3 加载了outter2 加载了outter1 ======================= 执行了wrapper1 执行了wrapper2 执行了wrapper3 from index """


浙公网安备 33010602011771号