2010-01-06 26 views
91

W django.utils.functional.py:Co robi funkcja "mro()"?

for t in type(res).mro(): # <----- this 
    if t in self.__dispatch: 
     return self.__dispatch[t][funcname](res, *args, **kw) 

Nie rozumiem mro(). Co robi i co oznacza "mro"?

+2

http://www.python.org/download/releases/2.3/mro – GodMan

+1

Ooph, co to za długa lektura. – paulmelnikow

Odpowiedz

164

Idź wzdłuż ...:

>>> class A(object): pass 
... 
>>> A.__mro__ 
(<class '__main__.A'>, <type 'object'>) 
>>> class B(A): pass 
... 
>>> B.__mro__ 
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>) 
>>> class C(A): pass 
... 
>>> C.__mro__ 
(<class '__main__.C'>, <class '__main__.A'>, <type 'object'>) 
>>> 

Dopóki mamy pojedynczy dziedziczenia __mro__ jest tylko krotka: klasy, jego podstawa, podstawa jego podstawy, a więc na maksymalnie object (tylko oczywiście pracuje dla klas w nowym stylu).

Teraz z dziedziczenia wielokrotnego ...:

>>> class D(B, C): pass 
... 
>>> D.__mro__ 
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>) 

... można również uzyskać pewność, że w __mro__, żadna klasa jest powielany, a nie klasa przychodzi po swoich przodkach, z zastrzeżeniem, że klasy, które najpierw wchodzą na tym samym poziomie dziedziczenia wielokrotnego (jak B i C w tym przykładzie) są od lewej do prawej.

Każdy atrybut, który dostajesz na instancji klasy, a nie tylko metody, jest konceptualnie sprawdzany wzdłuż __mro__, więc jeśli więcej niż jedna klasa wśród przodków definiuje tę nazwę, to powie Ci, gdzie ten atrybut zostanie znaleziony - w pierwszej klasie w __mro__, która definiuje tę nazwę.

+7

cześć, alex, czy jest jakaś różnica między D .__ mro__ i D.mro(). – zjm1126

+19

'mro' może być dostosowywane przez metaklass, jest wywoływane jeden raz przy inicjalizacji klasy, a wynik jest zapisywany w' __mro__' - patrz http://docs.python.org/library/stdtypes.html?highlight=mro# klasa .__ mro__. –

+13

Dlaczego jest nazywany ** porządkiem rozdzielczości metody ** zamiast ** porządkiem rozdzielczości atrybutów **? – Bentley4

69

mro() oznacza Order Resolution systemu. Zwraca listę typów, z których wywodzi się klasa, w kolejności, w jakiej są wyszukiwane.

MRO() lub __mro__ działa tylko na nowych klas stylów. W pythonie 3 działają bez żadnych problemów. Ale w python 2 te klasy muszą dziedziczyć z obiektów.

7

To prawdopodobnie pokaże kolejność rezolucji.

class A(object): 
    def dothis(self): 
     print('I am from A class') 

class B(A): 
    pass 

class C(object): 
    def dothis(self): 
     print('I am from C class') 

class D(B, C): 
    pass 

d_instance= D() 
d_instance.dothis() 
print(D.mro()) 

i odpowiedź będzie

I am from A class 
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>] 

Zasadą jest Departament pierwszy który w tym przypadku oznacza, D, B, A, C

Pythona zwykle wykorzystuje głębokość pierwszego kolejności podczas przeszukiwania dziedziczenia klas Ale kiedy dwie klasy dziedziczą z tej samej klasy, Python usuwa pierwszą wzmiankę o tej klasie z mro.

+1

Jak widać, zamówienie jest D, B, A, C – Stryker

+1

Co masz na myśli przez "Python usuwa pierwszą wzmiankę o tej klasie z mro."? –

+1

@RuthvikVaila: Myślę, że ta część jest po prostu źle sformułowana. W tym [wpisie na blogu] (http://python-history.blogspot.com/2010/06/method-resolution-order.html) o historii Pythona, zauważa Guido van Rossum (o schemacie MRO wprowadzonym w Pythonie 2.2) "Jeśli jakakolwiek klasa została zduplikowana w tym wyszukiwaniu, wszystkie oprócz ** ostatniego wystąpienia zostaną usunięte z listy MRO" (podkreślenie moje). Oznacza to, że może usunąć więcej niż tylko pierwszą "wzmiankę" o klasie. – martineau

Powiązane problemy