Chcę przesłonić dostęp do jednej zmiennej w klasie, ale normalnie zwrócić wszystkie inne. Jak to osiągnąć za pomocą__getattribute__
?
Wypróbowałem następujące rozwiązania (które powinny również zilustrować, co próbuję zrobić), ale pojawia się błąd rekursji:
class D(object):
def __init__(self):
self.test=20
self.test2=21
def __getattribute__(self,name):
if name=='test':
return 0.
else:
return self.__dict__[name]
>>> print D().test
0.0
>>> print D().test2
...
RuntimeError: maximum recursion depth exceeded in cmp
super(D, self).__getattribute__(name)
super().__getattribute__(name)
w Pythonie 3.Właściwie uważam, że
__getattr__
zamiast tego chcesz użyć specjalnej metody.Cytat z dokumentacji Pythona:
Uwaga: aby to zadziałało, instancja nie powinna mieć
test
atrybutu, więc wierszself.test=20
należy usunąć.źródło
__getattr__
dlatest
byłoby bezużyteczne, ponieważ zawsze znajdowałoby się ono „w zwykłych miejscach”.Dokumentacja języka Python:
Znaczenie:
Wzywasz atrybut o nazwie
__dict__
. Ponieważ jest to atrybut,__getattribute__
zostanie wywołany w poszukiwaniu__dict__
który domaga__getattribute__
który wzywa ... bla bla blaKorzystanie z klas bazowych
__getattribute__
pomaga znaleźć prawdziwy atrybut.źródło
Czy na pewno chcesz użyć
__getattribute__
? Co tak naprawdę próbujesz osiągnąć?Najłatwiej zrobić to, o co prosisz:
lub:
Edycja: Zwróć uwagę, że instancja
D
będzie miała różne wartościtest
w każdym przypadku. W pierwszym przypadkud.test
będzie to 20, w drugim 0. Zostawię ci wyjaśnienie, dlaczego.Edit2: Greg zwrócił uwagę, że przykład 2 zakończy się niepowodzeniem, ponieważ właściwość jest tylko do odczytu, a
__init__
metoda próbowała ustawić ją na 20. Bardziej kompletnym przykładem byłoby:Oczywiście jako klasa jest to prawie całkowicie bezużyteczne, ale daje ci pomysł, od którego możesz odejść.
źródło
Oto bardziej niezawodna wersja:
To nazywa __ getAttribute __ metodę z klasy nadrzędnej, w końcu spada z powrotem do obiektu. __ getattribute __ , jeśli inni przodkowie jej nie zastępują.
źródło
Jest wywoływana przed zwykłym wyszukiwaniem kropkowanym. Jeśli wzrośnie
AttributeError
, dzwonimy__getattr__
.Stosowanie tej metody jest raczej rzadkie. W bibliotece standardowej są tylko dwie definicje:
Najlepsze praktyki
Właściwym sposobem programowego kontrolowania dostępu do pojedynczego atrybutu jest
property
. KlasaD
powinna być zapisana w następujący sposób (z ustawieniem i usunięciem opcjonalnie w celu odtworzenia widocznego zamierzonego zachowania):I użycie:
Właściwość jest deskryptorem danych, dlatego jest pierwszą rzeczą, której szuka się w normalnym algorytmie wyszukiwania kropkowego.
Opcje dla
__getattribute__
Masz kilka opcji, jeśli absolutnie musisz zaimplementować wyszukiwanie dla każdego atrybutu za pośrednictwem
__getattribute__
.AttributeError
, powodując__getattr__
wywołanie (jeśli zaimplementowano)super
wywołania nadrzędnej (prawdopodobnieobject
) implementacji__getattr__
Na przykład:
To, czego pierwotnie chciałeś.
Ten przykład pokazuje, jak możesz zrobić to, czego pierwotnie chciałeś:
I będzie się tak zachowywać:
Przegląd kodu
Twój kod z komentarzami. Masz wykropkowane wyszukiwanie siebie w
__getattribute__
. Dlatego pojawia się błąd rekursji. Możesz sprawdzić, czy nazwa jest"__dict__"
i użyćsuper
do obejścia, ale to nie obejmuje__slots__
. Zostawię to jako ćwiczenie dla czytelnika.źródło