前言如何给装饰器传递参数,这个问题困扰了我很久,虽然Python版本更新了,但是这个问题终于解决了,特此记录。问题首先,我有一个像这样的装饰器文件路径helper/log_helper.pyimporttracebackfromfunctoolsimportwrapsfromloguruimportloggerdefmy_logger(count):defstep1(foo):@wraps(foo)defstep2(*args,**kwargs)尝试:Result=Foo(*ARGS,**KWARGS)logger.info(f"{result=},{count=}")Exceptexception:logger.exception(traceback.Format_exc())一个文件需要引用这个decoratordemo。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|信息|helper.log_helper:step2:18-result='inmainfunction',count=2这个装饰器的作用很简单,就是获取当前函数的返回值,以及传入的count值。OK,现在的问题是?给装饰器的参数传值呢,也就是说我的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()defnurretmain(self):"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"这样,我们就成功解决了这个问题,突然想起之前遇到的问题现在已经解决了,我希望它能帮助你。以上就是本次分享的全部内容。觉得文章还不错的话,请关注公众号:Python编程学习圈,每日干货分享,发送“J”还能领取大量学习资料。或者去编程学习网了解更多编程技术知识。
