bizercsdn 2020-09-17
def copy_properties(src,dst): # 提供一个函数,被封装函数属性 copy 到包装函数属性,保持被封装函数属性不变 dst.__name__=src.__name__ dst.__doc__=src.__doc__ dst.__qualname__=src.__qualname__ def logger(fn): def wrapper(*args,**kwargs): ‘i\‘m wrapper‘ print(‘begin‘) kin=fn(*args,**kwargs) print(‘after‘) return kin copy_properties(fn,wrapper) return wrapper @logger def lag(x,y): ‘i\‘m a function‘ return x+y print(‘name={}\ndoc={}‘.format(lag.__name__,lag.__doc__))
通过copy_properties函数将被包装函数的属性覆盖掉包装函数
凡是被装饰的函数都要复制这些属性
可以将copy_properties函数构建成装饰器函数,带参装饰器
import datetime,timedef copy_properties(src): def wrapper(dst): dst.__name__=src.__name__ dst.__doc__=src.__doc__ dst.__qualname__=src.__qualname__ return dst return wrapper def logger(fn): #logger中不能直接引用copy_properties中的嵌套函数,利用copy_properties的返回值进行引用,fn实参形成闭包,等价于copy_properteis.wrapper(有闭包) # => logger.wrapper = copy_properties.wrapper(logger.wrapper) @copy_properties(fn) def wrapper(*args,**kwargs): ‘this is the wrapper‘ print("args={},kwargs={}".format(args,kwargs)) start=datetime.datetime.now() ret=fn(*args,**kwargs) duration=datetime.datetime.now()-start print(‘function {} took {}s‘.format(fn.__name__,duration.total_seconds())) return ret return wrapper@loggerdef add(x,y): ‘this is the function‘ print(‘call add‘) time.sleep(2) return x+yadd(5,7)
import datetime,time def logger(fn): def wrapper(*args,**kwargs): print(‘args={}\nkwargs={}‘.format(args,kwargs)) start=datetime.datetime.now() kin=fn(*args,**kwargs) duration=(datetime.datetime.now()-start) print(‘function {} took {} seconds‘.format(fn.__name__,duration.total_seconds())) return kin return wrapper @logger def lag(x,y): time.sleep(2) return x+y print(lag(5,y=8))
带参装饰器
import datetime,timedef copy_properties(src): def wrapper(dst): dst.__name__=src.__name__ dst.__doc__=src.__doc__ dst.__qualname__=src.__qualname__ return dst return wrapperdef logger(t): def _logger(fn): @copy_properties(fn) def wrapper(*args,**kwargs): ‘i\‘m a wrapper‘ print(‘args:{}\nkwargs:{}‘.format(args,kwargs)) start=datetime.datetime.now() kin=fn(*args,**kwargs) duration=datetime.datetime.now()-start if duration.total_seconds()>t: print(‘function {} took {} seconds‘.format(fn.__name__,duration.total_seconds())) return kin return wrapper return _logger@logger(2)def lag(x,y): ‘i\‘m a function‘ time.sleep(2) return x+yprint(lag.__name__,lag.__doc__,lag.__qualname__)print(lag(5,y=9))
def kin(fn): return 10 @kin def hip(x,y): return x+y hip
hip 本来指向一个函数对象,但经过装饰后,指向int 10
def kin(fn): return kin @kin def hip(x,y): return x+y hip(50)
hip经过装饰后,指向了装饰器函数本身
import datetime,time def copy_properties(src): def wrapper(dst): dst.__name__=src.__name__ dst.__doc__=src.__doc__ dst.__qualname__=src.__qualname__ return dst return wrapper def logger(duration,func=lambda duration,name:print(‘{} took {} seconds‘.format(name,duration))): def _logger(fn): def wrapper(*args,**kwargs): start=datetime.datetime.now() kin=fn(*args,**kwargs) delta=(datetime.datetime.now()-start).total_seconds() if delta>duration: func(delta,fn.__name__) return kin return wrapper return _logger @logger(3) def hip(x,y): time.sleep(3) return x+y print(hip(5,y=6))