Respuestas:
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 una sola herencia, __mro__
es solo la tupla de: la clase, su base, la base de su base, y así sucesivamente hastaobject
(solo funciona para clases de estilo nuevo, por supuesto).
Ahora, con herencia múltiple ...:
>>> class D(B, C): pass
...
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
... también tiene la seguridad de que, en __mro__
, ninguna clase está duplicada, y ninguna clase viene después de sus antepasados, salvo que las clases que primero ingresan al 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 obtiene en la instancia de una clase, no solo los métodos, se busca conceptualmente a lo largo del __mro__
, por lo que, si más de una clase entre los antepasados define ese nombre, esto le indica dónde se encontrará el atributo, en la primera clase en el __mro__
que define ese nombre.
mro
puede ser personalizado por una metaclase, se llama una vez en la inicialización de la clase y el resultado se almacena en __mro__
- ver docs.python.org/library/… .
mro()
significa Método de resolución de la orden. Devuelve una lista de tipos de los que se deriva la clase, en el orden en que se buscan los métodos.
mro () o __mro__ solo funciona en nuevas clases de estilo. En python 3, funcionan sin ningún problema. Pero en Python 2 esas clases necesitan heredar object
.
Esto quizás muestre 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, lo que en este caso significaría D, B, A, C.
Python normalmente usa un primer orden de profundidad cuando busca clases heredadas, pero cuando dos clases heredan de la misma clase, Python elimina la primera mención de esa clase de mro.
El 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'>)
class B3
pero en el segundo caso se va class A
despuésclass B1