PySide はShibokenを使用して、C++ クラスから Qt の CPython バインディングを生成します。などの Qt python クラスはすべてQPushButton
C++ で実装されているため、上書きできません__class__
。
>>> button = QPushButton()
>>> button.__class__ = MyButton
TypeError: __class__ assignment: only for heap types
Shiboken のドキュメントによると
、メソッドが仮想 (オーバーライド可能) である限り、既にインスタンス化されたオブジェクトのメソッドにモンキー パッチ (またはダック パンチ)を適用できます。
import types
def override_text(self):
return 'overridden'
# Bind override_text() to button.
button.text = types.MethodType(override_text, button, QPushButton)
QPushButton
これをさらに進めると、 as としてサブクラス化し、メソッドを
インスタンス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)
- 注: 親クラスのメソッドを呼び出す古いスタイルを使用する必要があります。
メソッドが注入されたとき、self は実際には aであり、 a
ではないため
super()
、 a で失敗します。TypeError
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)
- 注:を直接
使用しないため、
QPushButton.text()
直接呼び出すことができます。self.__class__
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''