def add(x, y): print('add called. x={}, y={}'.format(x, y)) # 增加的记录功能 return x + y add(4, 5)
上面的代码满足了需求,但有缺点:
记录信息的功能,可以是一个单独的功能。显然和add函数耦合太紧密。加法函数属于业务功能,输出信息属于非功能代码,不该放在add函数中
import time import datetime def logger(wrapped): def wrapper(*args, **kwargs): start = datetime.datetime.now() ret = wrapped(*args, **kwargs) delta = (datetime.datetime.now() - start).total_seconds() print('{} tooks {}s'.format(wrapped.__name__, delat)) return ret return wrapper @logger #等价于add = logger(add) def add(x, y): time.sleep(1) return x + y print(add(4, 5)) ##等价于 logger(add)(4, 5)
被装饰后,函数名和文档都不对了。如何解决?
functools模块提供了一个wraps装饰器函数,本质上调用的是,update_wrapper,它就是一个属性复制函数。
wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
wrapped就是被包装函数
wrapper就是包装函数
用被包装函数的属性覆盖包装函数的同名属性
元组WRAPPER_ASSIGNMENTS中是要被覆盖的属性
module , name , qualname , doc , annotations
模块名、名称、限定名、文档、参数注解
import time from datetime import datetime from functools import wraps # def update(wrapped, wrapper): # wrapper.__name__ = wrapped.__name__ # wrapper.__doc__ = wrapped.__doc__ def logger(wrapped): @wraps(wrapped) def wrapper(*args, **kwargs): start = datetime.now() ret = wrapped(*args, **kwargs) delat = (datetime.now() - start).total_seconds() print('{} tooks {}s'.format(wrapped.__name__, delat)) return ret # update_wrapper(wrapper, wrapped) return wrapper @logger # add = logger(add) def add(x, y:int): "add description" # time.sleep(2) return x + y print(add(4, 5)) print(add.__name__, add.__doc__, add.__annotations__)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)