¿Enumerar todas las clases base en una jerarquía de clase dada?

Respuestas:

196

inspect.getmro(cls)funciona para las clases de estilo nuevas y antiguas y devuelve lo mismo que NewClass.mro(): una lista de la clase y todas sus clases ancestrales, en el orden utilizado para la resolución del método.

>>> class A(object):
>>>     pass
>>>
>>> class B(A):
>>>     pass
>>>
>>> import inspect
>>> inspect.getmro(B)
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
Jochen Ritzel
fuente
2
No funciona para las clases pyobjc :( Archivo "/Users/rbp/Projects/zzzzzzz/macmdtypes.py", línea 70, en coerce print inspect.getmro (ruta) Archivo "/System/Library/Frameworks/Python.framework/ Versiones / 2.7 / lib / python2.7 / inspect.py ", línea 348, en bases de búsqueda getmro (cls, resultado) Archivo" /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect .py ", línea 339, en _searchbases para base en cls .__ bases_ : AttributeError: el objeto ' NSTaggedDate' no tiene atributo '__bases '
rbp
17
@rbp Sospecho que tuvo el mismo problema que encontré: estaba intentando hacerlo en inspect.getmro(obj)lugar de hacerlo inspect.getmro(type(obj)).
esmit
44

Vea la __bases__propiedad disponible en una python class, que contiene una tupla de las clases 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>]
Creciente Fresco
fuente
55
Esto puede introducir duplicados. ¿Y es por eso que la documentación para getmroexplícitamente dice "Ninguna clase aparece más de una vez en esta tupla"?
Sridhar Ratnakumar
10
Precaución, __bases__solo sube un nivel . (Como su utilidad recursiva implica, pero una mirada superficial al ejemplo podría no captar eso.)
Bob Stein
32

inspect.getclasstree()creará una lista anidada de clases y sus bases. Uso:

inspect.getclasstree(inspect.getmro(IOError)) # Insert your Class instead of IOError.
Ned Batchelder
fuente
1
Ooh genial. Y para una salida aún mejor, ¡usa pprint! python -c 'import inspect; from pprint import pprint as pp; pp(inspect.getclasstree(inspect.getmro(IOError)))'
penguin359
20

puedes usar la __bases__tupla del objeto de clase:

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

La tupla devuelta por __bases__tiene todas sus clases base.

¡Espero eso ayude!

Mandel
fuente
Si su clase hereda de una clase que hereda de una clase, solo la primera parte de la cadena estará en su__bases__
Boris
Simple y limpio sin importar un módulo completo para una sola función.
Temperosa
8

En python 3.7 no necesita importar inspeccionar, type.mro le dará el resultado.

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

atención que en python 3.x cada clase hereda de la clase de objeto base.

Serjik
fuente
8

Según el documento de Python , también podemos simplemente usar el class.__mro__atributo o el class.mro()método:

>>> 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

YaOzI
fuente
2

Aunque la respuesta de Jochen es muy útil y correcta, ya que puede obtener la jerarquía de clases utilizando el método .getmro () del módulo de inspección, también es importante resaltar que la jerarquía de herencia de Python es la siguiente:

ex:

class MyClass(YourClass):

Una clase heredadora

  • Clase infantil
  • Clase derivada
  • Subclase

ex:

class YourClass(Object):

Una clase heredada

  • Clase de padres
  • Clase base
  • Superclase

Una clase puede heredar de otra: los atributos de la clase 'se heredan', en particular, sus métodos se heredan, esto significa que las instancias de una clase heredadora (secundaria) pueden acceder atribuidas a la clase heredada (principal)

instancia -> clase -> luego clases heredadas

utilizando

import inspect
inspect.getmro(MyClass)

le mostrará la jerarquía, dentro de Python.

Carson
fuente