Réponses:
Suivre...:
>>> 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'>)
>>>
Tant que nous avons un héritage unique, __mro__
est juste le tuple de: la classe, sa base, la base de sa base, et ainsi de suite jusqu'àobject
(ne fonctionne que pour les classes de nouveau style bien sûr).
Maintenant, avec l' héritage multiple ...:
>>> class D(B, C): pass
...
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
... vous avez également l'assurance que, dans __mro__
qu'aucune classe n'est dupliquée et qu'aucune classe ne vient après ses ancêtres, sauf que les classes qui entrent en premier au même niveau d'héritage multiple (comme B et C dans cet exemple) sont dans le __mro__
de gauche à droite.
Chaque attribut que vous obtenez sur l'instance d'une classe, pas seulement les méthodes, est recherché conceptuellement le long du __mro__
, donc, si plus d'une classe parmi les ancêtres définit ce nom, cela vous indique où l'attribut sera trouvé - dans la première classe de le __mro__
qui définit ce nom.
mro
peut être personnalisé par une métaclasse, est appelé une fois à l'initialisation de la classe et le résultat est stocké dans __mro__
- voir docs.python.org/library/… .
mro()
signifie Ordre de résolution des méthodes. Il renvoie une liste de types dont la classe est dérivée, dans l'ordre dans lequel les méthodes sont recherchées.
mro () ou __mro__ ne fonctionne que sur les nouvelles classes de style. En python 3, ils fonctionnent sans aucun problème. Mais en python 2, ces classes doivent hériter de object
.
Cela montrerait peut-être l'ordre de résolution.
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())
et la réponse serait
I am from A class
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>]
La règle est la profondeur d'abord, ce qui dans ce cas signifierait D, B, A, C.
Python utilise normalement un ordre de profondeur d'abord lors de la recherche de classes héritées, mais lorsque deux classes héritent de la même classe, Python supprime la première mention de cette classe de mro.
L'ordre de résolution sera différent dans l'héritage de diamants.
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
mais dans le second cas c'est aller class A
aprèsclass B1