Jak przesłonić __getattr__ w Pythonie bez naruszenia domyślnego zachowania?


185

Chcę zastąpić __getattr__metodę na klasie, aby zrobić coś wymyślnego, ale nie chcę przerywać domyślnego zachowania.

Jak to zrobić w odpowiedni sposób?


20
„Przerwa”, pyta, a nie „zmiana”. To dość jasne: „fantazyjne” atrybuty nie powinny zakłócać wbudowanych atrybutów i powinny zachowywać się tak bardzo, jak to możliwe. Odpowiedź Michaela jest zarówno poprawna, jak i pomocna.
olooney,

Odpowiedzi:


268

Przesłanianie __getattr__powinno być w porządku - __getattr__jest wywoływane tylko w ostateczności, tj. Jeśli w instancji nie ma atrybutów pasujących do nazwy. Na przykład, jeśli uzyskasz dostęp foo.bar, __getattr__zostanie wywołany tylko wtedy, gdy nie zostanie wywołany foożaden atrybut bar. Jeśli atrybut nie jest obsługiwany, podnieś AttributeError:

class Foo(object):
    def __getattr__(self, name):
        if some_predicate(name):
            # ...
        else:
            # Default behaviour
            raise AttributeError

Jednak w przeciwieństwie do __getattr__, __getattribute__zostanie wywołany jako pierwszy (działa tylko dla klas nowego stylu, tj. Dziedziczących po obiekcie). W takim przypadku możesz zachować domyślne zachowanie:

class Foo(object):
    def __getattribute__(self, name):
        if some_predicate(name):
            # ...
        else:
            # Default behaviour
            return object.__getattribute__(self, name)

Zobacz dokumentację Python, aby uzyskać więcej .


Bah, twoja edycja ma to samo, co pokazywałem w mojej odpowiedzi, +1.

12
Fajnie, Python nie lubi dzwonić do super- __getattr__żadnych pomysłów, co robić? ( AttributeError: 'super' object has no attribute '__getattr__')
gatoatigrado

1
Trudno powiedzieć bez obejrzenia kodu, ale wygląda na to, że żadna z nadklas nie definiuje getattr .
Colin vH

Działa to również z hasattr, ponieważ: „Jest to realizowane przez wywołanie getattr (obiekt, nazwa) i sprawdzenie, czy zgłasza wyjątek, czy nie”. docs.python.org/2/library/functions.html#hasattr
ShaBANG

1
-1 ten sposób zmodyfikować zachowanie domyślne. Teraz masz AttributeErrorbez kontekstu atrybutu w args wyjątku.
wim
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.