2012-10-13 14 views
8

Oprócz omijania dowolnych atrybutów instancji w interesie poprawności, domyślne wyszukiwanie metod specjalnych również pomija metodę __getattribute__() nawet metaklasu obiektu.Jakie specjalne metody pomijają __getattribute__ w Pythonie?

The docs wspomnieć specjalne metody, takie jak __hash__, __repr__ i __len__ i wiem z doświadczenia, że ​​obejmuje również __iter__ dla Pythona 2.7.

Cytując an answer to a related question:

„Magia __methods__() są traktowane specjalnie: są wewnętrznie przypisane do«szczeliny»w strukturze typu danych w celu przyspieszenia ich przeglądowej, a są one wzrok tylko w tych automaty. "

W dążeniu do poprawy moją odpowiedź na another question, muszę wiedzieć: Jakie metody konkretnie mówimy?

+0

Jakie metody są przypisane do gniazd? –

+7

Myślę, że każda metoda wymieniona [tutaj] (http://docs.python.org/reference/datamodel.html#specialnames). W każdym razie weź pod uwagę, że ma to zastosowanie tylko wtedy, gdy wywołasz metodę używając "jej składni". Na przykład 'a + 5' nie wywołuje' __getattribute__', natomiast 'a .__ dodaj __ (5)' * wywoła *. Zasadniczo "__getattribute__" jest wywoływane za każdym razem, gdy używasz kropki ('.') w celu uzyskania dostępu do atrybutu. – Bakuriu

+0

@Bururiu: Bardzo pouczające, dziękuję. – porgarmingduod

Odpowiedz

4

można znaleźć odpowiedź w python3 documentation dla object.__getattribute__, który stanowi:

Called bezwarunkowo wdrożyć atrybut dostęp do instancji klasy. Jeśli klasa również definiuje __getattr__(), to ostatnia nazwa nie będzie wywoływana, chyba że __getattribute__() albo wywoła ją jako jawnie, albo podniesie AttributeError. Ta metoda powinna zwrócić wartość atrybutu (obliczoną) lub podnieść wyjątek AttributeError. W celu uniknięcia nieskończonej rekursji w tej metodzie, jego implementacja powinna zawsze wywoływać metodę klasy bazowej o tej samej nazwie, aby uzyskać dostęp do wszelkich wymaganych atrybutów, na przykład obiektu. __getattribute__(self, name).

Uwaga

Ta metoda może być nadal pomijane kiedy patrzy się specjalne metody, jak w wyniku domniemanego inwokacji poprzez składni języka lub wbudowanej funkcji. Zobacz Wyszukiwanie metod specjalnych.

także strona this strona wyjaśnia dokładnie, jak działa ta "maszyna". Zasadniczo __getattribute__ jest wywoływane tylko wtedy, gdy uzyskujesz dostęp do atrybutu z operatorem . (kropka) (a także przez hasattr, jak wskazał Zagorulkin).

Zauważ, że strona, która nie określa szczególnych metod niejawnie spojrzał w górę, więc uznać, że to hold dla wszystkich z nich (który można znaleźć here.

+0

czy rzeczywiście sprawdziłeś? Sprawdziłem 2.7.9 i wygląda na to, że doktorzy nie są do końca zgodni. –

1

sprawdzone w 2.7.9

mogłam „t znaleźć jakiś sposób na ominięcie wywołanie __getattribute__, z którymkolwiek z magicznych metod, które znajdują się na object lub type:

# Preparation step: did this from the console 
# magics = set(dir(object) + dir(type)) 
# got 38 names, for each of the names, wrote a.<that_name> to a file 
# Ended up with this: 

a.__module__ 
a.__base__ 
#... 

Umieścić to na beginnin g tego pliku, którego nazwa została zmieniona na właściwy moduł python (asdf.py)

global_counter = 0 

class Counter(object): 
    def __getattribute__(self, name): 
     # this will count how many times the method was called 
     global global_counter 
     global_counter += 1 
     return super(Counter, self).__getattribute__(name) 

a = Counter() 
# after this comes the list of 38 attribute accessess 
a.__module__ 
#... 
a.__repr__ 
#... 

print global_counter # you're not gonna like it... it printer 38 

Potem próbowałem również uzyskać każda z tych nazw przez getattr and hasattr -> samego rezultatu. __getattribute__ został wywołany za każdym razem.

Więc jeśli ktoś ma inne pomysły ... Byłem zbyt leniwy, aby zajrzeć do kodu C tego, ale jestem pewien, że odpowiedź leży gdzieś tam.

Więc albo coś jest nie tak, albo doktorzy kłamią.

+1

Jeśli dobrze pamiętam, moje pytanie dotyczyło 'repr (a)' w przeciwieństwie do 'a .__ repr __()'. Minęło trochę czasu odkąd byłem w tym, ale domyślam się, że dostajesz wersję getattribute, ponieważ patrzysz na atrybuty, podczas gdy wbudowane metody, o których mówimy (globalne 'repr', nie' __repr__') omijają istnienie "__repr__". – porgarmingduod

+0

Zastąp '__getattribute__', aby wydać druk za każdym razem, gdy zostanie wywołany, a następnie wykonaj:' Counter ('a') + Counter ("a") 'i zobacz, że nic nie drukuje. Ponieważ omija standardową nazwę, wyszukuj i uderzaj w 'Counter .__ dict __ ['__ add __']' bezpośrednio lub jakąś taką głupią rzecz w imię optymalizacji. – justanr

Powiązane problemy