回答:
オーバーライド__getattr__
は問題ありません- __getattr__
最後の手段としてのみ呼び出されます。つまり、名前に一致するインスタンス内の属性がない場合です。たとえば、にアクセスするとfoo.bar
、という属性がない__getattr__
場合にのみfoo
呼び出されbar
ます。属性が処理したくないものである場合は、次のようにレイズしAttributeError
ます。
class Foo(object):
def __getattr__(self, name):
if some_predicate(name):
# ...
else:
# Default behaviour
raise AttributeError
ただし、とは異なり__getattr__
、__getattribute__
最初に呼び出されます(新しいスタイルクラス、つまりオブジェクトから継承するクラスでのみ機能します)。この場合、次のようにデフォルトの動作を維持できます。
class Foo(object):
def __getattribute__(self, name):
if some_predicate(name):
# ...
else:
# Default behaviour
return object.__getattribute__(self, name)
詳細については、Pythonのドキュメントをご覧ください。
__getattr__
いいですね、Pythonはスーパーインを呼び出すのが好きではないようです-何かアイデアはありますか?(AttributeError: 'super' object has no attribute '__getattr__'
)
AttributeError
で、例外引数に属性のコンテキストがありません。
class A(object):
def __init__(self):
self.a = 42
def __getattr__(self, attr):
if attr in ["b", "c"]:
return 42
raise AttributeError("%r object has no attribute %r" %
(self.__class__.__name__, attr))
>>> a = A()
>>> a.a
42
>>> a.b
42
>>> a.missing
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in __getattr__
AttributeError: 'A' object has no attribute 'missing'
>>> hasattr(a, "b")
True
>>> hasattr(a, "missing")
False
self.__class__.__name__
代わりにそれを使用する必要があると思いself.__class__
ます__repr__
Michaelの回答を拡張するために、を使用してデフォルトの動作を維持したい場合は__getattr__
、次のようにすることができます。
class Foo(object):
def __getattr__(self, name):
if name == 'something':
return 42
# Default behaviour
return self.__getattribute__(name)
これで、例外メッセージがよりわかりやすくなりました。
>>> foo.something
42
>>> foo.error
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __getattr__
AttributeError: 'Foo' object has no attribute 'error'
__getattr__
しました__getattribute__
か?