【发布时间】:2013-04-07 16:45:33
【问题描述】:
我正在尝试找到创建执行以下操作的类装饰器的最佳方法:
- 将一些函数注入到装饰类中
- 在装饰类'
__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__ 或将我的呼叫注入其他地方?我真正需要的是在创建对象后的某个时间调用我的self._debugSignals()。我也希望它自动发生,这就是为什么我认为__init__ 之后是个好地方。
额外的杂项。装修说明
可能值得一提的是这个装饰器的一些背景。你可以找到完整的代码here。装饰器的重点是自动附加到任何 PyQt 信号并在它们发出时打印。当我装饰自己的QtCore.QObject 子类时,装饰器工作正常,但我最近一直在尝试automatically decorate all QObject children。
我想在应用程序中有一个“调试”模式,我可以在其中自动打印所有信号,以确保事情按照我的预期进行。我确信这会导致大量调试,但我仍然想看看发生了什么。
问题是我当前版本的装饰器导致segfault when replacing QtCore.QObject.__init__。我试过调试这个,但代码都是 SIP 生成的,我没有太多经验。
所以,我想知道是否有更安全、更 Pythonic 的方式在 __init__ 之后注入函数调用,并希望避免段错误。
【问题讨论】:
-
不是解决方案,而是一些信息:
QtCore.QObject.__init__在 Qt 库中实现,即。在 C++ 中,这就是为什么你不能简单地替换__init__。 -
@rainer 这很有道理。我试图查看
QtCore.QObject.__init__源代码,但我迷失在创建包装器等的所有 sip/C++ 魔法中。这解释了为什么我的装饰器适用于基于 python 的对象(或至少不包装的对象)与 sip/c++ 层密切相关)。但是,我在想也许有一种更简洁的方法可以在不劫持__init__的情况下实现这种行为,因为我也不太喜欢基于 python 的对象的这种行为。但是,对于 python 对象,“它只是有效”。