需求
def add1(x,y): print("call add, x+y") #日志输出的控制台 return x+y
以上函数完成了需求,但是存在以下缺点:
def add1(x,y): return x+y def logger(fn): print("begin") x = fn(4,5) print("end") return x print(logger(add1))
但这里fn调用传参是个问题
def add1(x,y): return x+y def logger(fn,*args,**kwargs): print("begin") x = fn(*args,**kwargs) #这里是在解构 print("end") return x print(logger(add1,5,y=10))
def add(x,y): return x+y def logger(fn): def wrapper(*args,**kwargs): print("begin") x = fn(*args,**kwargs) #这里是在解构 print("end") return x return wrapper print(logger(add)(5,y = 10))
def logger(fn): def wrapper(*args,**kwargs): print("begin") x = fn(*args,**kwargs) #这里是在解构 print("end") return x return wrapper @logger def add(x,y): return x+y print(add(45,500))
@logger是装饰器的语法
装饰器和高阶函数
import datetime import time def logger(fn): def wrapper(*args,**kwargs): print("begin") print("args={},kwargs={}".format(args,kwargs)) start = datetime.datetime.now() x = fn(*args,**kwargs) #这里是在解构 duration = datetime.datetime.now() -start print("function {} took {}s.".format(fn.__name__,duration.total_seconds())) return x return wrapper @logger # add = logger(add) def add(x,y): print("==========call add==========") time.sleep(2) return x+y print(add(45,500))
python文档
def add(x,y): """This is function of addition""" a = x+y return x+y print("name={}\ndoc={}".format(add.__name__,add.__doc__)) print(help(add))
副作用出现的问题:
def logger(fn): def wrapper(*args,**kwargs): "I am a wrapper" print("begin") x = fn(*args,**kwargs) #这里是在解构 print("end") return x return wrapper @logger #add= logger(add) def add(x,y): "This is a function for add" return x+y print("name={},doc={}".format(add.__name__,add.__doc__))
原函数对象的属性都被替换了,而使用装饰器,我们的需求是查看被封装函数的属性,如何解决呢?
提供一个函数,被封装函数属性==copy==>包装函数属性
def copy_properties(src,dest): #可以改造成装饰器 dest.__name__ = src.__name__ dest.__doc__ = src.__doc__ def logger(fn): def wrapper(*args,**kwargs): "I am a wrapper" print("begin") x = fn(*args,**kwargs) #这里是在解构 print("end") return x copy_properties(fn,wrapper) return wrapper @logger #add= logger(add) def add(x,y): "This is a function for add" return x+y print("name={},doc={}".format(add.__name__,add.__doc__))
def copy_properties(src):#可以改造成装饰器 def _copy_properties(dest): dest.__name__ = src.__name__ dest.__doc__ = src.__doc__ return dest return _copy_properties def logger(fn): @copy_properties(fn) #wrapper = copy_properties(fn)(wrapper) def wrapper(*args,**kwargs): "I am a wrapper" print("begin") x = fn(*args,**kwargs) #这里是在解构 print("end") return x return wrapper @logger #add= logger(add) def add(x,y): "This is a function for add" return x+y print("name={},doc={}".format(add.__name__,add.__doc__))
获取函数执行时长,对时长超过阈值的函数记录一下
import datetime import time def copy_properties(src):#可以改造成装饰器 def _copy_properties(dest): dest.__name__ = src.__name__ dest.__doc__ = src.__doc__ return dest return _copy_properties def loger(duration): def _logger(fn): @copy_properties(fn) def wrapper(*args,**kwargs): start = datetime.datetime.now() x = fn(*args, **kwargs) delta=(datetime.datetime.now()-start).total_seconds() print(‘so slow‘) if delta > duration else print(‘so fast‘) return x return wrapper return _logger @loger(5) def add(x,y): time.sleep(6) return x + y print(add(10,24))
带参装饰器:
import datetime import time def copy_properties(src):#可以改造成装饰器 add def _copy_properties(dest): #wrapper dest.__name__ = src.__name__ dest.__doc__ = src.__doc__ return dest return _copy_properties def loger(duration,func=lambda name,duration:print(‘{} took {}s‘.format(name,duration))): #loger(5)(add) duration=5 def _logger(fn): #loger(5)(add) fn = add @copy_properties(fn) #wrapper = _copy_properties(fn)(wrapper) def wrapper(*args,**kwargs): start = datetime.datetime.now() x = fn(*args, **kwargs) delta=(datetime.datetime.now()-start).total_seconds() if delta > duration: func(fn.__name__,duration) return x return wrapper return _logger @loger(5) #add = loger(5)(add) def add(x,y): time.sleep(6) return x + y print(add(10,24))
functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
import datetime, time, functools def logger(duration, func=lambda name, duration: print(‘{} took {}s‘.format(name, duration))): def _logger(fn): def wrapper(*args,**kwargs): start = datetime.datetime.now() ret = fn(*args,**kwargs) delta = (datetime.datetime.now() - start).total_seconds() if delta > duration: func(fn.__name__, duration) return ret return functools.update_wrapper(wrapper, fn) return _logger @logger(5) # add = logger(5)(add) def add(x,y): time.sleep(1) return x + y print(add(5, 6), add.__name__, add.__wrapped__, add.__dict__, sep=‘\n‘)
@functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
import datetime, time, functools def logger(duration, func=lambda name, duration: print(‘{} took {}s‘.format(name, duration))): def _logger(fn): @functools.wraps(fn) def wrapper(*args,**kwargs): start = datetime.datetime.now() ret = fn(*args,**kwargs) delta = (datetime.datetime.now() - start).total_seconds() if delta > duration: func(fn.__name__, duration) return ret return wrapper return _logger @logger(5) # add = logger(5)(add) def add(x,y): time.sleep(1) return x + y print(add(5, 6), add.__name__, add.__wrapped__, add.__dict__, sep=‘\n‘)
原文:https://www.cnblogs.com/xzkzzz/p/11377065.html