终于解决了使用Python装饰器中的一个痛点

 前言

在宿城等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供成都网站制作、网站建设 网站设计制作定制网站,公司网站建设,企业网站建设,品牌网站建设,成都全网营销,外贸网站制作,宿城网站建设费用合理。

如何给装饰器的参数传参,这个问题曾经困扰我好久,虽然Python版本的更新,现在这个问题终于解决了,特此记录。

疑问

首先我有一个这样的装饰器文件路径helper/log_helper.py

 
 
 
  1. import traceback
  2. from functools import wraps
  3. from loguru import logger
  4. def my_logger(count):
  5.     def step1(foo):
  6.         @wraps(foo)
  7.         def step2(*args, **kwargs):
  8.             try:
  9.                 result = foo(*args, **kwargs)
  10.                 logger.info(f"{result=},{count=}")
  11.             except Exception:
  12.                 logger.exception(traceback.format_exc())
  13.         return step2
  14.     return step1

然后我有个文件需要引用这个装饰器demo.py

 
 
 
  1. from helper.log_helper import my_logger
  2. class Demo:
  3.     @my_logger(count=2)
  4.     def main(self):
  5.         return "in main function"
  6. if __name__ == '__main__':
  7.     d = Demo()
  8.     d.main()

输出结果如下

 
 
 
  1. 2020-10-16 11:43:12.001 | INFO     | helper.log_helper:step2:18 - result='in main function',count=2

这个装饰器的作用很简单,就是获取当前函数的返回值,和传入的count值。

好,现在问题来了?

如果给装饰器的参数传值呢,也就是说我的count=2,是通过传值的形式。你想到可能是这样

 
 
 
  1. from helper.log_helper import my_logger
  2. COUNT=2
  3. class Demo:
  4.     @my_logger(count=COUNT)
  5.     def main(self):
  6.         return "in main function"
  7. if __name__ == '__main__':
  8.     d = Demo()
  9.     d.main()

ok,这样确实可以,我们还可以使用再简化一步

 
 
 
  1. from functools import partial
  2. from helper.log_helper import my_logger
  3. COUNT=2
  4. my_logger = partial(my_logger,count=2)
  5. class Demo:
  6.     @my_logger()
  7.     def main(self):
  8.         return "in main function"
  9. if __name__ == '__main__':
  10.     d = Demo()
  11.     d.main()

暂时来看我们搞定了传参数的问题,这时候我们想如果外界调用了Demo类的main方法,并且向指定count的值怎么办呢?

我们知道外界调用Demo类传参的唯一途径就是向__init__里进行传参数,按照这个思路我们只能这么写了,

 
 
 
  1. class Demo:
  2.     def __init__(self):
  3.         count =2
  4.     @my_logger(count=self.count)
  5.     def main(self):
  6.         return "in main function"

但是这样并不可以,我们得到错误信息

 
 
 
  1. NameError: name 'self' is not defined

在装饰器中无法使用self.形式的参数,难道这个问题解决不了么?

问题解决

在Python3.7之前确实没什么可行的方案。

我们知道在Python3.7的时候引入了dataclasses,我们可以通过它来简化__init__。

改下我们的代码

 
 
 
  1. from functools import partial
  2. from helper.log_helper import my_logger
  3. from dataclasses import dataclass
  4. @dataclass()
  5. class Demo:
  6.     count: int = 2
  7.     logger: my_logger = partial(my_logger, count)
  8.     @logger()
  9.     def main(self):
  10.         return "in main function"
  11. if __name__ == '__main__':
  12.     d = Demo()
  13.     d.main()

如果使用Python3.8那么可以直接忽略掉dataclass

 
 
 
  1. class Demo:
  2.     count: int = 2
  3.     logger: my_logger = partial(my_logger, count)
  4.     @logger()
  5.     def main(self):
  6.         return "in main function"

这样我们就成功的解决了这个问题,突然想起来之前遇到的这个难题,现在算是解决了,希望对你有帮助。

当前名称:终于解决了使用Python装饰器中的一个痛点
本文URL:http://www.shufengxianlan.com/qtweb/news38/109488.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联