前言如何给装饰器传递参数,这个问题困扰了我很久,虽然Python版本更新了,但是这个问题终于解决了,特此记录。问题首先,我有一个像这样的装饰器文件路径helper/log_helper.pyimporttracebackfromfunctoolsimportwrapsfromloguruiimportloggerdefmy_logger(count):defstep1(foo):@wraps(foo)defstep2(*args,**kwargs):try:result=foo(*args,**kwargs)logger.info(f"{result=},{count=}")exceptException:logger.exception(traceback.format_exc())returnstep2returnstep1然后我有个文件需要引用这个装饰器demo.pyfromhelper.log_helperimportmy_loggerclassDemo:@my_logger(count=2)defmain(self):return"inmainfunction"if__name__=='__main__':d=Demo()d.main()输出结果如下2020-10-1611:43:12.001|INFO|helper.log_helper:step2:18-result='inmainfunction',count=2这个装饰器的作用很简单,就是获取当前函数的返回值和传入的计数值。好了,现在问题来了?如果我给装饰器的参数传一个值呢,也就是说我的count=2是传一个值的形式。你觉得可能是这样的fromhelper.log_helperimportmy_loggerCOUNT=2classDemo:@my_logger(count=COUNT)defmain(self):return"inmainfunction"if__name__=='__main__':d=Demo()d.main()ok,这是确实可以,我们还可以使用一个更简化的fromfunctoolsimportpartialfromhelper.log_helperimportmy_loggerCOUNT=2my_logger=partial(my_logger,count=2)classDemo:@my_logger()defmain(self):return"inmainfunction"if__name__=='__main__':d=Demo()d。main()我们暂时解决了传递参数的问题。这时候我们想到,如果外界调用了Demo类的main方法,指定了count的值,怎么办呢?我们知道,外界调用Demo类传递参数的唯一方式就是给__init__传递参数,按照这个思路,我们只能这样写,classDemo:def__init__(self):count=2@my_logger(count=self.count)defmain(self):return"inmainfunction"但这不不,我们得到错误消息NameError:name'self'isnotdefinedcannotuseself。装饰器里的参数,这个问题不就解决了吗?Python3.7之前确实没有可行方案。我们知道在Python3.7中引入了数据类,我们可以通过它来简化__init__。更改我们的代码fromfunctoolsimportpartialfromhelper.log_helperimportmy_loggerfromdataclassesimportdataclass@dataclass()classDemo:count:int=2logger:my_logger=partial(my_logger,count)@logger()defmain(self):return"inmainfunction"if__name__=='__main__':d=Demo()d.main()如果使用Python3.8,可以忽略dataclassclassDemo:count:int=2logger:my_logger=partial(my_logger,count)@logger()defmain(self):return"inmainfunction"这样我们就可以成功解决了这个问题,突然想起之前遇到的问题,现在解决了,希望对你有帮助。
