Dans 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 veut dire "mro"?
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 simplement le tuple de: la classe, sa base, sa base, etc. jusqu'à la variable object
(ne fonctionne bien sûr que pour les classes de style nouveau).
Maintenant, avec multiple 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, dans __mro__
, aucune classe n'est dupliquée et qu'aucune classe ne succède à ses ancêtres, sauf que les classes qui entrent d'abord au même niveau d'héritage multiple (comme B et C dans cet exemple) sont déjà présentes. le __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 du __mro__
. Ainsi, si plusieurs classes parmi les ancêtres définissent ce nom, cela vous indique où l'attribut sera trouvé - dans la première classe. dans le __mro__
qui définit ce nom.
mro()
est synonyme de résolution de méthode. Il retourne une liste des types dont la classe est dérivée, dans l'ordre dans lequel ils sont recherchés.
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 d'objets.
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 depth-first 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 diamant.
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'>)