204

クラスのメソッドをオーバーライド__getattr__して何か凝ったことをしたいのですが、デフォルトの動作を壊したくありません。

これを行う正しい方法は何ですか?

4

3 に答える 3

295

オーバーライド__getattr__は問題ないはずです-__getattr__最後の手段としてのみ呼び出されます。つまり、名前に一致する属性がインスタンスにない場合にのみ呼び出されます。たとえば、にアクセスするfoo.barと、と呼ばれる属性がない__getattr__場合にのみ呼び出されます。属性が処理したくない属性である場合は、次の値を上げます。foobarAttributeError

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のドキュメントを参照してください。

于 2010-03-08T23:35:42.623 に答える
36
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
于 2010-03-08T23:50:51.193 に答える
22

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'
于 2015-08-11T14:30:27.060 に答える