193 votes

Enumérez toutes les classes de base dans la hiérarchie d'une classe donnée ?

Étant donné une classe Foo (qu'il s'agisse d'un nouveau style ou non), comment générer tous les classes de base - n'importe où dans la hiérarchie de l'héritage - elle issubclass de ?

245voto

Jochen Ritzel Points 42916

inspect.getmro(cls) fonctionne à la fois pour les nouvelles et les anciennes classes de style et renvoie la même chose que NewClass.mro() : une liste de la classe et de toutes ses classes ancêtres, dans l'ordre utilisé pour la résolution des méthodes.

>>> class A(object):
>>>     pass
>>>
>>> class B(A):
>>>     pass
>>>
>>> import inspect
>>> inspect.getmro(B)
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)

4 votes

Ne fonctionne pas pour les classes pyobjc :( File "/Users/rbp/Projects/zzzzzzz/macmdtypes.py", line 70, in coerce print inspect.getmro(path) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect.py", line 348, in getmro searchbases(cls, result) Fichier "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect.py", ligne 339, dans _searchbases for base in cls.__bases_. : AttributeError : ' L'objet 'NSTaggedDate' ne possède pas d'attribut '__bases '

30 votes

@rbp je soupçonne que vous avez eu le même problème que moi : vous essayiez de faire inspect.getmro(obj) au lieu de inspect.getmro(type(obj)) .

53voto

Crescent Fresh Points 54070

Voir le __bases__ propriété disponible sur un python class qui contient un tuple des classes de base :

>>> def classlookup(cls):
...     c = list(cls.__bases__)
...     for base in c:
...         c.extend(classlookup(base))
...     return c
...
>>> class A: pass
...
>>> class B(A): pass
...
>>> class C(object, B): pass
...
>>> classlookup(C)
[<type 'object'>, <class __main__.B at 0x00AB7300>, <class __main__.A at 0x00A6D630>]

6 votes

Cela peut introduire des doublons. Et c'est pourquoi la documentation de getmro dit explicitement "Aucune classe n'apparaît plus d'une fois dans ce tuple" ?

12 votes

Attention, __bases__ ne fait que monter un niveau . (Comme l'implique votre utilité récursive, mais un regard superficiel sur l'exemple pourrait ne pas s'en rendre compte).

44voto

Ned Batchelder Points 128913

inspect.getclasstree() créera une liste imbriquée de classes et de leurs bases. Utilisation :

inspect.getclasstree(inspect.getmro(IOError)) # Insert your Class instead of IOError.

4 votes

Ooh, joli. Et pour une sortie encore plus belle, utilisez pprint ! python -c 'import inspect; from pprint import pprint as pp; pp(inspect.getclasstree(inspect.getmro(IOError)))'

31voto

YaOzI Points 129

Selon le Document Python on peut aussi simplement utiliser class.__mro__ ou class.mro() méthode :

>>> class A:
...     pass
... 
>>> class B(A):
...     pass
... 
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
>>> A.__mro__
(<class '__main__.A'>, <class 'object'>)
>>> object.__mro__
(<class 'object'>,)
>>>
>>> B.mro()
[<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
>>> A.mro()
[<class '__main__.A'>, <class 'object'>]
>>> object.mro()
[<class 'object'>]
>>> A in B.mro()
True

21voto

mandel Points 1460

Vous pouvez utiliser le __bases__ tuple de l'objet classe :

class A(object, B, C):
    def __init__(self):
       pass
print A.__bases__

Le tuple retourné par __bases__ a toutes ses classes de base.

J'espère que cela vous aidera !

4 votes

Si votre classe hérite d'une classe qui hérite d'une autre classe, seule la première partie de la chaîne se trouvera dans sa classe. __bases__

0 votes

Simple et propre sans importer un module entier pour une seule fonction.

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