Pregunta

En django.utils.functional.py:

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

No entiendo mro().¿Qué hace y qué significa "mro"?

¿Fue útil?

Solución

Seguir a lo largo...:

>>> 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'>)
>>> 

Mientras tengamos herencia única, __mro__ es solo la tupla de:la clase, su base, la base de su base, y así hasta object (por supuesto, solo funciona para clases de nuevo estilo).

Ahora con múltiple herencia...:

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

...también tienes la seguridad de que, en __mro__, ninguna clase está duplicada y ninguna clase viene después de sus antecesoras, salvo que las clases que entran primero en el mismo nivel de herencia múltiple (como B y C en este ejemplo) están en el __mro__ de izquierda a derecha.

Cada atributo que obtienes en la instancia de una clase, no sólo los métodos, se busca conceptualmente a lo largo del __mro__, entonces, si más de una clase entre los ancestros define ese nombre, esto le indica dónde se encontrará el atributo: en la primera clase del __mro__ que define ese nombre.

Otros consejos

mro() significa Resolución método de pedido. Se devuelve una lista de tipos de la clase se deriva de, en el orden en que se han buscado métodos.

MRO () o __ __ MRO sólo funciona en las nuevas clases de estilo. En Python 3, trabajan sin ningún problema. Pero en Python 2 esas clases tienen que heredar de objetos.

Esto tal vez mostrar el orden de resolución.

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())

y la respuesta sería

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

La regla es primero en profundidad, que en este caso significaría D, B, A, C.

Python normalmente utiliza un profundidad-primero orden cuando se busca clases heredado mientras que cuando dos clases heredan de la misma clase, Python quita la primera mención de que clase de MRO.

Orden de resolución será diferente en la herencia de diamantes.

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


class B1(A):
    def dothis(self):
        print('I am from B1 class')
    # pass


class B2(object):
    def dothis(self):
        print('I am from B2 class')
    # pass


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


# Diamond inheritance
class D1(B1, B3):
    pass


class D2(B1, B2):
    pass


d1_instance = D1()
d1_instance.dothis()
# I am from B1 class
print(D1.__mro__)
# (<class '__main__.D1'>, <class '__main__.B1'>, <class '__main__.B3'>, <class '__main__.A'>, <class 'object'>)


d2_instance = D2()
d2_instance.dothis()
# I am from B1 class
print(D2.__mro__)
# (<class '__main__.D2'>, <class '__main__.B1'>, <class '__main__.A'>, <class '__main__.B2'>, <class 'object'>)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top