PySide 使用Shiboken 从
它的 C++ 类。所有 Qt python 类,例如QPushButton 都是
用 C++ 实现,这就是为什么你不能覆盖 __class__。
>>> button = QPushButton()
>>> button.__class__ = MyButton
TypeError: __class__ assignment: only for heap types
根据 Shiboken 的文档,你可以monkey patch (or duck punch)
只要方法是已经实例化的对象上的方法
虚拟(可覆盖):
import types
def override_text(self):
return 'overridden'
# Bind override_text() to button.
button.text = types.MethodType(override_text, button, QPushButton)
更进一步,您可以将QPushButton 子类化为MyButton,并且
将MyButton 中的方法动态注入QPushButton
实例。使MyButton 成为QPushButton 的子类纯粹是
可选,但允许您创建自己的 MyButton 实例
除了修改后的QPushButton 实例。
让我们将MyButton 定义为QPushButton 的子类。
class MyButton(QPushButton):
def text(self):
# This will override QPushButton's text() method.
print("inside MyButton.text()")
return QPushButton.text(self)
- 注意:您必须使用旧式调用父类方法。
super() 以 TypeError 失败,因为 self 实际上是 QPushButton
而不是MyButton 注入方法时。
或者,如果您想采用更多的 mixin 方法,让我们定义 MyButtonOverrides:
class MyButtonOverrides(object):
def text(self):
# This will override QPushButton's text() method.
print("inside MyButtonOverrides.text()")
return self.__class__.text(self)
- 注意:您可以通过
self.__class__ 直接拨打QPushButton.text()
因为你不会直接使用MyButtonOverrides。
现在让我们定义extend_instance(),它将注入您的覆盖
从MyButton(或MyButtonOverrides)到QPushButton的方法
实例:
import inspect
def extend_instance(obj, cls):
for name, attr in vars(cls).items():
if inspect.isroutine(attr):
# Bind instance, class and static methods to *obj*.
setattr(obj, name, attr.__get__(obj, obj.__class__))
如果您希望您的类方法保持绑定到它们的原始类
(例如,MyButton)然后使用以下内容:
def extend_instance(obj, cls):
for name, attr in vars(cls).items():
if inspect.isroutine(attr):
if isinstance(attr, classmethod):
# Bind class methods to *cls*.
setattr(obj, name, attr.__get__(cls, cls))
else:
# Bind instance and static methods to *obj*.
setattr(obj, name, attr.__get__(obj, obj.__class__))
通过我的测试,这适用于 Python 2.7 和 3.3,但应该
在 2.6+ 和 3+ 上工作。
最后修改按钮,使用extend_instance()。
>>> button = QPushButton()
>>> extend_instance(button, MyButton)
>>> button.text()
inside MyButton.text()
u''