__getattribute__
を無効にすることを再検討し、代わりにobject.__getattr__()
hookを使用することを強くお勧めします。この方法は、任意の不足している属性のために自動的に呼び出され、dir()
または__dict__
イントロスペクションとは干渉しません:あなたはあなたの属性のクラスをチェックするために失敗したため、
class GetAttribute(object):
def __init__(self):
self.predefined_attribute = "First attribute"
def __getattr__(self, attr):
# self.__dict__ can be used here but is not needed for your
# sample usecase.
return randint(0, 9999)
独自の実装には欠陥があります。 __dict__
はクラスの記述子であり、self.__dict__
にアクセスしようとするとobject.__getattribute__
も処理され、無限再帰がトリガーされます。 object.__getattribute__
最初にを使用して問題を完全に回避できます。あなたは、これがスローする可能性AttributeError
例外をキャッチできます。
def __getattribute__(self, attr):
try:
return object.__getattribute__(self, attr)
except AttributeError:
return randint(0, 9999)
より多くの痛みを伴うパスが再実装descriptor protocolは、試験前に、あなたの__dict__
属性を取得するために、次のようになります。
def __getattribute__(self, attr):
cls = type(self)
# retrieve the __dict__ descriptor, and bind it to the instance
__dict__ = cls.__dict__['__dict__'].__get__(self)
# test against the instance dictionary and all classes in the MRO
if attr not in __dict__ and not any(attr in c.__dict__ for c in cls.__mro__):
return randint(0, 9999)
return object.__getattribute__(self, attr)
か、self.__dict__
にアクセスすることができましたvia object.__getattribute__(self, '__dict__')
MROクラスもテストする必要があります。これはインスタンスの属性も提供するためです。 X.__class__
がGetAttribute
ではなく、ランダムな整数を返すことは望ましくありません。
しかし、このユースケースはすでに、より洗練された簡単なオプション__getattr__
を実装することでカバーされています。
最後に、object.__getattribute__(self, ...)
を使用する代わりに、super().__getattribute__(...)
を使用して、クラス階層内で他の__getattribute__
フックをスキップしないようにする必要があります。
:属性は
__getattribute__
が上AttributeError
を提起することをルックアップ__getattr__
だけと呼ばれています。ただし、* class *を最初にチェックする必要があります。 –