Respostas:
Acompanhe ...:
>>> 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'>)
>>>
Desde que tenhamos uma herança única, __mro__
é apenas a tupla de: a classe, sua base, sua base e assim por diante.object
(funciona apenas para classes de novo estilo, é claro).
Agora, com herança múltipla ...:
>>> class D(B, C): pass
...
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
... você também tem a garantia de que, em __mro__
, nenhuma classe é duplicada e nenhuma classe vem após seus ancestrais, exceto que as classes que primeiro entram no mesmo nível de herança múltipla (como B e C neste exemplo) estão no __mro__
esquerda para a direita.
Todos os atributos que você obtém na instância de uma classe, não apenas métodos, são conceitualmente pesquisados ao longo de __mro__
, portanto, se mais de uma classe entre os ancestrais definir esse nome, isso informa onde o atributo será encontrado - na primeira classe em o __mro__
que define esse nome.
mro
pode ser personalizado por uma metaclasse, é chamado uma vez na inicialização da classe e o resultado é armazenado em __mro__
- consulte docs.python.org/library/… .
mro()
significa Ordem de resolução de método. Ele retorna uma lista de tipos dos quais a classe é derivada, na ordem em que são pesquisados por métodos.
mro () ou __mro__ funciona apenas em novas classes de estilo. No python 3, eles funcionam sem problemas. Mas no python 2 essas classes precisam herdar object
.
Talvez isso mostre a ordem da resolução.
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())
e resposta seria
I am from A class
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]
A regra é a profundidade em primeiro lugar, o que neste caso significaria D, B, A, C.
O Python normalmente usa uma ordem de profundidade ao pesquisar classes herdadas, mas quando duas classes são herdadas da mesma classe, o Python remove a primeira menção dessa classe do mro.
A ordem da resolução será diferente na herança do diamante.
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
mas no segundo caso, é ir paraclass A
depoisclass B1