当前位置: 首页 > 后端技术 > Python

给装饰器添加参数

时间:2023-03-26 16:46:06 Python

一个简单的场景:我有一个装饰器,用来给函数计时,现在我想给函数的运行时间加上一个时间偏移time_lag,这个时间偏移不是一个常量,我想通过参数传入装饰器实现。实现一:importtimefromfunctoolsimportwrapsdeftimer_func(func,time_lag):@wraps(func)defwer(*args,**kwargs):t1=time.time()r=func(*args,**kwargs)t2=time.time()cost=t2-t1+time_lagprint('timecost%s'%cost)returnrreturnwerdeffunc(n:int):whilen>0:n=n-1返回na=timer_func(func,time_lag=10)a(1000000)但是这种实现方式不能语法糖@,每次都必须通过函数调用来实现,失去了装饰器简洁方便的特点。因此,使用另一种实现方式,只需要在原来的装饰函数外再嵌套一层外层函数,将要传入装饰器的函数传入最外层函数即可。实现方法如下:实现方法二:fromfunctoolsimportwrapsimporttimedeftimer(time_lag):defdecorator(func):@wraps(func)defwer(*args,**kwargs):t1=time.time()r=func(*args,**kwargs)t2=time.time()cost=t2-t1res=cost+time_lagprint('timecost%s'%res)returnfunc(*args,**kwargs)#返回函数本身的结果returnwer#returninnerfunctionreturndecorator#Returnouterfunctiondeffunc(n:int):'''thisisafunctest:paramn:::return:'''whilen>0:n=n-1returnn>>>a=timer(10)#返回外部函数,#passintime_lag=10>>>print(a).decoratorat0x000002027D8E5E50>>>>b=a(func)#返回内部函数>>>print(b)>>>c=b(999999)#调用内部函数返回结果>>>print(c)timecost10.0697963237762450上面一步一步的调用过程只是为了展示清楚。功能看似复杂,其实本质思想还是闭包的思想,只是在装饰器中外面嵌套了一层外层函数,每个外层函数返回它的下一层内层函数。最里面的函数返回调用该函数的结果。这个方法也可以通过语法糖简洁调用:@timer(10)#passintime_lag=10deffunc(n:int):whilen>0:n=n-1returnn>>>func(99999)timecost10.008002042770386@timer(20)#传入time_lag=20deffunc1(n:int):whilen>0:n=n-1returnn>>>func1(22222222)timecost21.447203874588013创建带参数的日志装饰器CreateAlog装饰器,通过传递参数deflogged(level,name=None,message=None):defdecorator(func):logname=nameifnameelsefunc.将日志的输出级别、名称和信息传递给装饰器。__module__log=logging.getLogger(logname)logmsg=messageifmessageelsefunc.__name__@wraps(func)defwrapper(*args,**kwargs):log.log(level,message)返回func(*args,**kwargs)returnwrapperreturndecorator@logged(logging.DEBUG,'test_name')deffunc(a):returna+1