Comment obtenir les parents d'une classe Python?

202

Comment puis-je obtenir la ou les classes parentes d'une classe Python?

John Smith
la source

Réponses:

233

Utilisez l'attribut suivant:

cls.__bases__

De la documentation :

Le tuple des classes de base d'un objet de classe.

Exemple:

>>> str.__bases__
(<type 'basestring'>,)

Un autre exemple:

>>> class A(object):
...   pass
... 
>>> class B(object):
...   pass
... 
>>> class C(A, B):
...   pass
... 
>>> C.__bases__
(<class '__main__.A'>, <class '__main__.B'>)
Ayman Hourieh
la source
1
Pour obtenir les bases d'un objet instancié, procédez type(C()).__bases__comme indiqué ci
citynorman
106

Si vous voulez tous les ancêtres plutôt que les immédiats, utilisez inspect.getmro :

import inspect
print inspect.getmro(cls)

Utilement, cela vous donne toutes les classes d'ancêtres dans «l'ordre de résolution des méthodes» - c'est-à-dire l'ordre dans lequel les ancêtres seront vérifiés lors de la résolution d'une méthode (ou, en fait, de tout autre attribut) - les méthodes et autres attributs vivent dans le même espace de noms en Python, après tout ;-).

Alex Martelli
la source
34
Vous pouvez également simplement utiliser cls.__mro__(au moins dans Python 3.5)
naught101
@ naught101, plz en faire une réponse complète. Je l'ai presque raté, et je le pense aussi, beaucoup d'autres personnes.
Shihab Shahriar Khan
14

Les classes de nouveau style ont une méthode mro que vous pouvez appeler qui renvoie une liste des classes parentes dans l'ordre de résolution de la méthode.

DasIch
la source
Qu'est-ce qui compte comme classe de nouveau style? Il semble que je puisse l'utiliser avec les modèles Django, mais tout ce qui hérite de objectne semble pas répondre mro.
Brian Kung
1
considérant un objet x, nous pouvons obtenir l'ordre de résolution de la méthode avec l'appel que type(x).mro() nous pouvons considérer si xa ClassXcomme classe de base avec: ClassX in type(x).mro()
648trindade
13

La manière la plus RAPIDE , pour voir tous les parents, et DANS L'ORDRE , utilisez simplement le__mro__

c'est à dire repr(YOUR_CLASS.__mro__)


>>>
>>>
>>> import getpass
>>> getpass.GetPassWarning.__mro__

sorties, DANS L' ORDRE


(<class 'getpass.GetPassWarning'>, <type 'exceptions.UserWarning'>,
<type 'exceptions.Warning'>, <type 'exceptions.Exception'>, 
<type 'exceptions.BaseException'>, <type 'object'>)
>>>

Voilà. La "meilleure" réponse en ce moment, a 182 votes (comme je tape ceci) mais c'est tellement plus simple que certains alambiqués pour la boucle, examinant les bases d' une classe à la fois, sans mentionner quand une classe étend DEUX ou plusieurs parents Des classes. L'importation et l'utilisation inspectne couvrent que la portée inutilement. Honnêtement, c'est dommage que les gens ne sachent pas simplement utiliser les fonctions intégrées

J'espère que ça aide!

PyTis
la source
@John Smith stackoverflow.com/users/139885/john-smith , j'espère que vous voyez cette réponse. Si vous l'aimez, faites-le moi savoir avec un upvote!
PyTis
1
En fait, il inspect.getmrosuffit d'appeler l' __mro__objet, comme vous pouvez le voir sur github.com/python/cpython/blob/… . L'utilisation getmroproduit un code plus propre et plus lisible. Bien que sauter un appel de fonction soit en effet plus rapide.
tna0y
9

Utilisez des bases si vous voulez simplement obtenir les parents, utilisez __mro__(comme indiqué par @ naught101) pour obtenir l'ordre de résolution de la méthode (afin de savoir dans quel ordre les init ont été exécutées).

Bases (et d'abord obtenir la classe pour un objet existant):

>>> some_object = "some_text"
>>> some_object.__class__.__bases__
(object,)

Pour mro dans les versions récentes de Python:

>>> some_object = "some_text"
>>> some_object.__class__.__mro__
(str, object)

Évidemment, quand vous avez déjà une définition de classe, vous pouvez simplement l'appeler __mro__directement:

>>> class A(): pass
>>> A.__mro__
(__main__.A, object)
PascalVKooten
la source
3

Si vous voulez vous assurer qu'ils seront tous appelés, utilisez-les superà tous les niveaux.

Mike Graham
la source
Une fois que vous utilisez super, vous devez l'utiliser à tous les niveaux de toute façon, c'est pourquoi vous devez documenter son utilisation de manière explicite. Aussi, vous voudrez peut-être savoir que le super ne fonctionne pas sur toutes les classes ...
DasIch