クラス内のクラスの属性の変更をインターセプトする - Python
-
21-08-2019 - |
質問
私は pygame と Python をいじっていますが、クラスの属性が変更されたときに関数を呼び出せるようにしたいと考えています。私の現在の解決策は次のとおりです。
class ExampleClass(parentClass):
def __init__(self):
self.rect = pygame.rect.Rect(0,0,100,100)
def __setattr__(self, name, value):
parentClass.__setattr__(self,name,value)
dofancystuff()
Firstclass = ExampleClass()
これは正常に動作し、rect 値を変更すると dofancystuff が呼び出されます。 Firsclass.rect = pygame.rect.Rect(0,0,100,100)
. 。でも私が言うなら Firstclass.rect.bottom = 3
. __setattr__
そして、そこでは空想的なものは呼び出されません。
そこで私の質問は、サブクラスの属性への変更をどのようにインターセプトできるかということだと思います。
編集:また、私がこれを間違った方法で行っている場合は、Python に関してはあまり詳しくないことを教えてください。
解決
まあ、簡単な答えは、あなたがすることはできませんです。 Firstclass.rect = <...>
の場合は、あなたの__setattr__
が呼び出されます。しかしFirstclass.rect.bottom = 3
の場合のRectインスタンスの__setattr__
メソッドが呼び出されます。私が見る唯一の解決策は、あなたが__setattr__
メソッドを上書きpygame.rect.Rectの派生クラスを作成することです。あなたはまた、サルはのRectクラスにパッチを適用することができますが、これは正当な理由のために推奨されます。
他のヒント
あなたは__getattr__
に呼ばれるべき、Firstclass.rect
を試すことができます。
しかし、その代わりに次の操作を行います。pygame.rect
のために別のクラス(?ExampleClass.rect
のサブクラス)を作成します。そのクラスで__setattr__
を実装します。今、あなたはrect
のためにあなたのExampleClass
メンバーに設定されます何でも語られます。あなたはまだ今だけあなた自身__setattr__
クラスのバージョンをインスタンス化してください...
ExampleClass
でrect
を実装(とのの必要があります)することができます
ところで:オブジェクトとは対照的に、それはクラスのように見えるよう...、あなたのオブジェクトのFirstclass
を呼び出さないでください。
これは質問の答えではありませんが、関連しています:
self.__dict__[name] = value
おそらくそれよりも優れています
parentClass.__setattr__(self, name, value)
これは、Python ドキュメント (setattr">http://docs.python.org/2/reference/datamodel.html?highlight=setattr#object) で推奨されています。設定) そして、parentClass の動作について何も想定していないため、一般的なケースではとにかく意味がありません。 設定.
わーい、求められていないアドバイスは 4 年も遅すぎました!
私はあなたがこの難しさを持っている理由は、他の回答で提供されるより少しより多くの情報を値すると考えています。
問題は、あなたが行う場合は、次のとおりです。
myObject.attribute.thing = value
あなたは、属性に値を代入していません。コードがこれに相当します:
anAttribute = myObject.attribute
anAttribute.thing = value
それはmyObjectということで見ていたよう、すべてあなたが属性を取得し、それをやっています。あなたが属性を設定していない。
一つの解決策であるためにあなたがコントロールするあなたの属性のサブクラスを作り、そして__setattr__定義することができます。
あなたは、異なる種類の属性の多くを持っており、それらのすべてのために個々のサブクラスをたくさんしたくない場合は意味を成して別の解決策は、属性にファサードを返すために__getattribute__または__getattr__をオーバーライドすることですその__setattr__方法で関連動作を行います。私はこれを自分で行うことをしようとしていませんでしたが、私はあなたが任意のオブジェクトのためのファサードとして動作するシンプルなファサードクラスを作ることができるはずと想像します。
ケアは __getattribute__するの選択に取られる必要があるだろうそして、 __getattr__ に。詳細については、前の文にリンクドキュメントを参照してくださいが、__getattr__が使用されている場合は、基本的には、実際の属性は、トップが__getattr__は、それらの要求を処理し、__getattribute__が使用されている場合、それは属性を取得する必要がありますように、何らかの形で難読化/カプセル化されることがあります基本クラスへの呼び出しを経由してます。
あなたがやろうとしているすべては、いくつかのrectsが更新されているかどうかを判断された場合は、、これはやり過ぎです。