ink_Ocelot 发表于 2021-6-27 20:46:59

Python类装饰器的相关问题

本帖最后由 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()后依旧出错

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

装饰器代码如下:

class EPro:
    def __init__(self,func):
            
      self.__func = func

    def __get__(self, instance, owner):
      '''
      instance:实例
      owner:类
      
      '''

      #self.__instance = instance
      #print(self.__func)
      #print(self.__instance)

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


附输出日志:

------------------------------
2021-06-27 20:25:28,270 - Logger - INFO
*** 程序开始运行 时间:Sun Jun 27 20:25:28 2021 ***
------------------------------
2021-06-27 20:25:28,283 - Logger - INFO
现在正在进入类中方法.
------------------------------
2021-06-27 20:25:40,181 - Logger - INFO
现在正在进入类中方法.
------------------------------
2021-06-27 20:25:40,232 - Logger - INFO
现在正在进入类中方法.
------------------------------
2021-06-27 20:25:40,391 - Logger - ERROR
*** 错误通告 ***
发生时间:Sun Jun 27 20:25:40 2021
具体时间戳:1624796740.391237
错误描述:'NoneType' object is not callable
类:main
方法:mainLoop
详细信息:
Traceback (most recent call last):
File "K:\xxx\main.py", line 115, in __get__
    return self.__func(instance)
File "K:\xxx\main.py", line 176, in mainLoop
    self.fpsCheck()
TypeError: 'NoneType' object is not callable
------------------------------
2021-06-27 20:25:40,420 - Logger - ERROR
*** 错误通告 ***
发生时间:Sun Jun 27 20:25:40 2021
具体时间戳:1624796740.4202187
错误描述:'NoneType' object is not callable
类:main
方法:__init__
详细信息:
Traceback (most recent call last):
File "K:\xxx\main.py", line 115, in __get__
    return self.__func(instance)
File "K:\xxx\main.py", line 150, in __init__
    self.mainLoop()
TypeError: 'NoneType' object is not callable
------------------------------
2021-06-27 20:25:40,458 - Logger - ERROR
一个错误发生了,导致了程序异常退出.
详细信息:
Traceback (most recent call last):
File "K:\xxx\main.py", line 193, in <module>
    app = main()
TypeError: 'NoneType' object is not callable
------------------------------
2021-06-27 20:25:40,476 - Logger - INFO
*** 程序终止运行 时间:Sun Jun 27 20:25:40 2021 ***


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

请回答问题时标注回答问题序号,谢谢!

nahongyan1997 发表于 2021-6-27 21:50:40

本帖最后由 nahongyan1997 于 2021-6-27 21:51 编辑

我无视了你的四个问题,但是我觉得我应该解决了你真正的问题,请看代码:
class Demo:
    # 定义装饰器
    @classmethod
    def widget(self,func):
      # 使用闭包的方式
      def a(self,*args,**kwargs):
            print("in")
            func(self)
            print("out")
      
      return a
      
      
class Demo1:
    # 调用装饰器
    @Demo.widget
    def pp(self):
      print("1")
      
app = Demo1()
app.pp()

打印结果:
in
1
out

解决你的问题花了我二十分钟的时间,这还{:10_256:} {:10_256:} 不给个最佳吗{:10_254:}
页: [1]
查看完整版本: Python类装饰器的相关问题