187 votes

Que fait "mro()" ?

Sur django.utils.functional.py :

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

Je ne comprends pas. mro() . Que fait-il et que signifie "mro" ?

5 votes

277voto

Alex Martelli Points 330805

Suivez-moi.. :

>>> 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 seul héritage, __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 type nouveau, bien sûr).

Maintenant, avec multiple l'héritage... :

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

...vous obtenez également l'assurance que, en __mro__ aucune classe n'est dupliquée, et aucune classe ne vient après ses ancêtres, sauf que les classes qui entrent pour la première fois au même niveau d'héritage multiple (comme B et C dans cet exemple) sont dans la classe __mro__ de gauche à droite.

Chaque attribut que vous obtenez sur l'instance d'une classe, et pas seulement les méthodes, est conceptuellement recherché le long de l'arbre d'accès de la classe. __mro__ Ainsi, 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 l'arborescence __mro__ qui définit ce nom.

11 votes

Bonjour, Alex, y a-t-il une différence entre D.__mro__ et D.mro().

32 votes

mro peut être personnalisé par une métaclasse, est appelé une fois lors de l'initialisation de la classe, et le résultat est stocké dans le fichier __mro__ -- voir docs.python.org/library/ .

30 votes

Pourquoi s'appelle-t-il ordre de résolution des méthodes au lieu de ordre de résolution des attributs ?

103voto

Ned Batchelder Points 128913

mro() est l'abréviation de Method Resolution Order. 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() y __mro__ ne fonctionnent que sur les nouvelles classes de style. Dans Python 3, ils fonctionnent sans aucun problème. En Python 2, cependant, ces classes doivent hériter de object .

20voto

Stryker Points 1474

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 celle de la profondeur d'abord, ce qui dans ce cas signifierait D, B, A, C.

Python utilise normalement un profondeur d'abord lors de la recherche de classes héritantes, mais lorsque deux classes héritent de la même classe, Python supprime la première mention de cette classe dans mro.

3voto

Girish Gupta Points 681

L'ordre de résolution sera différent dans l'héritage des 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'>)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X