Dans le livre Python in a Nutshell (2e édition), il y a un exemple qui utilise
des classes de style ancien pour montrer comment les méthodes sont résolues dans l'ordre de résolution classique et en
quoi est-ce différent avec le nouvel ordre.
J'ai essayé le même exemple en réécrivant l'exemple dans un nouveau style mais le résultat n'est pas différent de ce qui a été obtenu avec des classes de style ancien. La version python que j'utilise pour exécuter l'exemple est 2.5.2. Voici l'exemple:
class Base1(object):
def amethod(self): print "Base1"
class Base2(Base1):
pass
class Base3(object):
def amethod(self): print "Base3"
class Derived(Base2,Base3):
pass
instance = Derived()
instance.amethod()
print Derived.__mro__
L'appel instance.amethod()
s'imprime Base1
, mais selon ma compréhension du MRO avec un nouveau style de classes, la sortie aurait dû être Base3
. L'appel Derived.__mro__
s'imprime:
(<class '__main__.Derived'>, <class '__main__.Base2'>, <class '__main__.Base1'>, <class '__main__.Base3'>, <type 'object'>)
Je ne sais pas si ma compréhension de la MRO avec les nouvelles classes de style est incorrecte ou si je fais une erreur stupide que je ne suis pas capable de détecter. Veuillez m'aider à mieux comprendre la MRO.
L'ordre de résolution des méthodes de Python est en fait plus complexe que la simple compréhension du modèle de diamant. Pour vraiment le comprendre, jetez un œil à la linéarisation C3 . J'ai trouvé qu'il était vraiment utile d'utiliser des instructions d'impression lors de l'extension de méthodes pour suivre la commande. Par exemple, que pensez-vous de la sortie de ce modèle? (Remarque: le 'X' est supposé être deux arêtes croisées, pas un nœud et ^ signifie des méthodes qui appellent super ())
Avez-vous eu ABDCEFG?
Après de nombreux essais d'erreur, j'ai proposé une interprétation informelle de la théorie des graphes de la linéarisation C3 comme suit: (Quelqu'un s'il vous plaît laissez-moi savoir si c'est faux.)
Prenons cet exemple:
la source
super
a des arguments requis.Le résultat que vous obtenez est correct. Essayez de changer la classe de base de
Base3
toBase1
et de comparer avec la même hiérarchie pour les classes classiques:Maintenant, il sort:
Lisez cette explication pour plus d'informations.
la source
Vous voyez ce comportement parce que la résolution de la méthode est la profondeur d'abord, pas la largeur d'abord. L'héritage de Dervied ressemble à
Alors
instance.amethod()
amethod
, donc il est appelé.Cela se reflète dans
Derived.__mro__
. Répétez simplementDerived.__mro__
et arrêtez lorsque vous trouvez la méthode recherchée.la source