鱼C论坛

 找回密码
 立即注册
查看: 1488|回复: 1

[已解决]Python类装饰器的相关问题

[复制链接]
发表于 2021-6-27 20:46:59 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 ink_Ocelot 于 2021-6-27 20:48 编辑

最近正在做一个用装饰器来检测脚本执行情况并输出项目的模块
我想要装饰的函数是在类中的,也就是方法
假设我的装饰器类在deco,另一个类A中被装饰的方法func
但是当装饰类中的函数时,需要传入实例self
如果用__call__,只能获取到*args和*kwargs,也就是写在括号里的参数
那么就会报错,提示缺少参数
所以我转而使用__get__方法
但是__get__方法只能获取实例和类,不能获取参数
然后我将类A中的所有需要参数的方法改为不需要参数的方法
但是不管我怎么试,他总会在进入第三个方法后提示'NoneType' object is not callable
也就是None不能作为方法使用
这种错误大概出现于:None(),这种使用方法
而装饰器大概讲就是将A.func()变成了deco(A.func())
所以我想是在装饰后传回了一个None,导致了出错
但是我将__get__里调用函数的方法前加了return传回func()后依旧出错

备注:将装饰器注释掉后程序运行正常

装饰器代码如下:

  1. class EPro:
  2.     def __init__(self,func):
  3.               
  4.         self.__func = func

  5.     def __get__(self, instance, owner):
  6.         '''
  7.         instance:实例
  8.         owner:类
  9.         
  10.         '''

  11.         #self.__instance = instance
  12.         #print(self.__func)
  13.         #print(self.__instance)

  14.         try:
  15.             
  16.             logger.info("现在正在进入类[{0}]中方法[{1}].".format(owner.__name__, self.__func.__name__))
  17.             return self.__func(instance)
  18.             print("退出方法:{}.".format(self.__func.__name__))
  19.          
  20.         except Exception as e:
  21.             
  22.             logger.error("*** 错误通告 ***\n发生时间:{0}\n具体时间戳:{1}\n错误描述:{2}\n类:{3}\n方法:{4}\n详细信息:".format(
  23.                 time.ctime(), time.time(), e.args[0], owner.__name__, self.__func.__name__), exc_info = True)
复制代码


附输出日志:

  1. ------------------------------
  2. 2021-06-27 20:25:28,270 - Logger - INFO
  3. *** 程序开始运行 时间:Sun Jun 27 20:25:28 2021 ***
  4. ------------------------------
  5. 2021-06-27 20:25:28,283 - Logger - INFO
  6. 现在正在进入类[main]中方法[__init__].
  7. ------------------------------
  8. 2021-06-27 20:25:40,181 - Logger - INFO
  9. 现在正在进入类[main]中方法[mainLoop].
  10. ------------------------------
  11. 2021-06-27 20:25:40,232 - Logger - INFO
  12. 现在正在进入类[main]中方法[fpsCheck].
  13. ------------------------------
  14. 2021-06-27 20:25:40,391 - Logger - ERROR
  15. *** 错误通告 ***
  16. 发生时间:Sun Jun 27 20:25:40 2021
  17. 具体时间戳:1624796740.391237
  18. 错误描述:'NoneType' object is not callable
  19. 类:main
  20. 方法:mainLoop
  21. 详细信息:
  22. Traceback (most recent call last):
  23.   File "K:\xxx\main.py", line 115, in __get__
  24.     return self.__func(instance)
  25.   File "K:\xxx\main.py", line 176, in mainLoop
  26.     self.fpsCheck()
  27. TypeError: 'NoneType' object is not callable
  28. ------------------------------
  29. 2021-06-27 20:25:40,420 - Logger - ERROR
  30. *** 错误通告 ***
  31. 发生时间:Sun Jun 27 20:25:40 2021
  32. 具体时间戳:1624796740.4202187
  33. 错误描述:'NoneType' object is not callable
  34. 类:main
  35. 方法:__init__
  36. 详细信息:
  37. Traceback (most recent call last):
  38.   File "K:\xxx\main.py", line 115, in __get__
  39.     return self.__func(instance)
  40.   File "K:\xxx\main.py", line 150, in __init__
  41.     self.mainLoop()
  42. TypeError: 'NoneType' object is not callable
  43. ------------------------------
  44. 2021-06-27 20:25:40,458 - Logger - ERROR
  45. 一个错误发生了,导致了程序异常退出.
  46. 详细信息:
  47. Traceback (most recent call last):
  48.   File "K:\xxx\main.py", line 193, in <module>
  49.     app = main()
  50. TypeError: 'NoneType' object is not callable
  51. ------------------------------
  52. 2021-06-27 20:25:40,476 - Logger - INFO
  53. *** 程序终止运行 时间:Sun Jun 27 20:25:40 2021 ***
复制代码



问题:
1.如何解决 'NoneType' object is not callable?
2.是否能不使用__get__而使用__call__来完成传入参数的问题?
3.(问题类似2)能否在__call__中获取实例和类?
4.在调试时发现加入__get__后__call__并不会执行(当然可能是执行前就出错弹出了),能否解释这个现象?

请回答问题时标注回答问题序号,谢谢!
最佳答案
2021-6-27 21:50:40
本帖最后由 nahongyan1997 于 2021-6-27 21:51 编辑

我无视了你的四个问题,但是我觉得我应该解决了你真正的问题,请看代码:
  1. class Demo:
  2.     # 定义装饰器
  3.     @classmethod
  4.     def widget(self,func):
  5.         # 使用闭包的方式
  6.         def a(self,*args,**kwargs):
  7.             print("in")
  8.             func(self)
  9.             print("out")
  10.         
  11.         return a
  12.         
  13.         
  14. class Demo1:
  15.     # 调用装饰器
  16.     @Demo.widget
  17.     def pp(self):
  18.         print("1")
  19.         
  20. app = Demo1()
  21. app.pp()
复制代码


打印结果:
  1. in
  2. 1
  3. out
复制代码


解决你的问题花了我二十分钟的时间,这还 不给个最佳吗
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-6-27 21:50:40 | 显示全部楼层    本楼为最佳答案   
本帖最后由 nahongyan1997 于 2021-6-27 21:51 编辑

我无视了你的四个问题,但是我觉得我应该解决了你真正的问题,请看代码:
  1. class Demo:
  2.     # 定义装饰器
  3.     @classmethod
  4.     def widget(self,func):
  5.         # 使用闭包的方式
  6.         def a(self,*args,**kwargs):
  7.             print("in")
  8.             func(self)
  9.             print("out")
  10.         
  11.         return a
  12.         
  13.         
  14. class Demo1:
  15.     # 调用装饰器
  16.     @Demo.widget
  17.     def pp(self):
  18.         print("1")
  19.         
  20. app = Demo1()
  21. app.pp()
复制代码


打印结果:
  1. in
  2. 1
  3. out
复制代码


解决你的问题花了我二十分钟的时间,这还 不给个最佳吗
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-22 06:29

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表