使用装饰器在__init__之后注入函数调用

dur*_*2.0 7 python decorator pyqt4

我正在尝试找到创建类装饰器的最佳方法,该装饰器执行以下操作:

  1. 在装饰类中注入一些函数
  2. 迫使这些功能一个通话结束后,装饰类__init__被称为

目前,我只是保存对"原始" __init__方法的引用,并将其替换为__init__调用原始和我的附加功能的方法.它看起来类似于:

orig_init = cls.__init__

def new_init(self, *args, **kwargs):
    """
    'Extend' wrapped class' __init__ so we can attach to all signals
    automatically
    """

    orig_init(self, *args, **kwargs)
    self._debugSignals()

cls.__init__ = new_init
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来"扩充"原件__init__或在其他地方注入我的电话?我真正需要的只是self._debugSignals()在创建对象后的某个时间调用它.我也希望它自动发生,这就是为什么我认为以后__init__是一个好地方.

额外的错误.装饰说明

值得一提的是这个装饰器的一些背景知识.你可以在这里找到完整的代码.装饰器的要点是自动附加到任何PyQt信号并在它们被发射时打印.当我装饰我自己的子类时QtCore.QObject,装饰器工作正常,但是我最近一直试图自动装饰所有QObject孩子.

我希望在应用程序中有一个"调试"模式,我可以自动打印所有信号,以确保事情按照我的预期进行.我相信这会导致TONS的调试,但我仍然希望看到发生了什么.

问题是我当前版本的装饰器在更换时QtCore.QObject.__init__导致了段错误.我试图调试这个,但代码是所有SIP生成的,我没有太多的经验.

所以,我想知道是否有更安全,更pythonic的方式来注入一个函数调用后__init__,希望避免段错误.

wil*_*art 7

根据这篇文章这个答案,另一种方法是通过自定义元类.这将工作如下(在Python 2.7中测试):

# define a new metaclass which overrides the "__call__" function
class NewInitCaller(type):
    def __call__(cls, *args, **kwargs):
        """Called when you call MyNewClass() """
        obj = type.__call__(cls, *args, **kwargs)
        obj.new_init()
        return obj


# then create a new class with the __metaclass__ set as our custom metaclass
class MyNewClass(object):
    __metaclass__ = NewInitCaller
    def __init__(self):
        print "Init class"
    def new_init(self):
        print "New init!!"

# when you create an instance
a = MyNewClass()
>>> Init class
>>> New init!!
Run Code Online (Sandbox Code Playgroud)

基本思路是:

  1. 当你调用MyNewClass()它时搜索元类,发现你已经定义了NewInitCaller

  2. __call__调用元类 函数.

  3. 此函数MyNewClass使用创建实例type,

  4. 该实例运行自己的__init__(打印"Init类").

  5. 元类然后调用new_init实例的函数.