鱼C论坛

 找回密码
 立即注册
查看: 1220|回复: 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()后依旧出错

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

装饰器代码如下:
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[0], 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
现在正在进入类[main]中方法[__init__].
------------------------------
2021-06-27 20:25:40,181 - Logger - INFO
现在正在进入类[main]中方法[mainLoop].
------------------------------
2021-06-27 20:25:40,232 - Logger - INFO
现在正在进入类[main]中方法[fpsCheck].
------------------------------
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__并不会执行(当然可能是执行前就出错弹出了),能否解释这个现象?

请回答问题时标注回答问题序号,谢谢!
最佳答案
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

解决你的问题花了我二十分钟的时间,这还 不给个最佳吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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

解决你的问题花了我二十分钟的时间,这还 不给个最佳吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-15 06:49

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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