python - 使用装饰器在 __init__ 之后注入(inject)函数调用

标签 python pyqt4 decorator

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

  1. 向装饰类中注入(inject)一些函数
  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

是否有更好的方法来“增强”原始 __init__ 或将我的调用注入(inject)其他地方?我真正需要的是让我的 self._debugSignals() 在创建对象后的某个时间被调用。我也希望它自动发生,这就是为什么我认为 __init__ 之后是个好地方。

额外杂项。装饰笔记

关于这个装饰器的一些背景可能值得一提。您可以找到完整代码 here .装饰器的要点是自动附加到任何 PyQt 信号并在它们发出时打印。当我装饰我自己的 QtCore.QObject 子类时,装饰器工作正常,但是我最近一直在尝试 automatically decorate all QObject children .

我想在应用程序中有一个“调试”模式,我可以在其中自动打印所有信号,以确保一切按我的预期进行。我确信这会导致大量调试,但我仍然想看看发生了什么。

问题是我当前版本的装饰器导致 segfault when replacing QtCore.QObject.__init__ .我试过调试它,但代码都是 SIP 生成的,我没有太多经验。

所以,我想知道是否有更安全、更 pythonic 的方法来在 __init__ 之后注入(inject)函数调用并希望避免段错误。

最佳答案

基于 this postthis answer ,另一种方法是通过自定义 metaclass .这将按如下方式工作(在 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!!

基本思想是:

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

  2. 元类__call__ 函数被调用。

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

  4. 该实例运行自己的 __init__(打印“Init class”)。

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

关于python - 使用装饰器在 __init__ 之后注入(inject)函数调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16017397/

相关文章:

oop - 代理模式和装饰者模式的区别

python - 为什么即使批量大小为 1 也会出现内存分配错误?

python - 我应该在哪里保存应用程序的数据?

python - PyQt 上下文菜单

python - 仅当 QProcess Stdout 包含子字符串时才打印它

c++ - 这是什么 C++ 习语/模式

python 属性装饰器

python - 遍历数据库表中所有行的最佳方法

python - 根据整个字符串对 AB 字符串列表进行排序

用于保存和恢复 UI 小部件值的 Python PyQt4 函数?