¿Cómo conseguir los padres de una clase de Python?

202

¿Cómo puedo obtener la (s) clase (s) padre (s) de una clase de Python?

John Smith
fuente

Respuestas:

233

Use el siguiente atributo:

cls.__bases__

De los documentos :

La tupla de las clases base de un objeto de clase.

Ejemplo:

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

Otro ejemplo:

>>> class A(object):
...   pass
... 
>>> class B(object):
...   pass
... 
>>> class C(A, B):
...   pass
... 
>>> C.__bases__
(<class '__main__.A'>, <class '__main__.B'>)
Ayman Hourieh
fuente
1
Para obtener las bases de un objeto instanciado, haga lo type(C()).__bases__que se menciona más abajo
citynorman
106

Si desea todos los antepasados ​​en lugar de solo los inmediatos, use inspect.getmro :

import inspect
print inspect.getmro(cls)

De manera útil, esto le proporciona todas las clases de ancestros en el "orden de resolución de métodos", es decir, el orden en el que se verificarán los ancestros al resolver un método (o, en realidad, cualquier otro atributo), los métodos y otros atributos viven en el mismo espacio de nombres en Python, después de todo ;-).

Alex Martelli
fuente
34
También puede usar cls.__mro__(al menos en Python 3.5)
naught101
@ naught101, por favor conviértalo en una respuesta completa. Casi me lo pierdo, y también lo hará, creo que muchas otras personas.
Shihab Shahriar Khan
14

Las clases de estilo nuevo tienen un método mro al que puede llamar que devuelve una lista de clases primarias en orden de resolución de método.

DasIch
fuente
¿Qué cuenta como una clase de nuevo estilo? Parece que puedo usar esto con los modelos de Django, pero cualquier cosa que simplemente herede objectno parece responder mro.
Brian Kung
1
considerando un objeto x, podemos obtener el orden de resolución del método con la llamada type(x).mro() que podemos considerar si xtiene ClassXcomo clase base con: ClassX in type(x).mro()
648trindade
13

La forma MÁS RÁPIDA , para ver a todos los padres, Y EN ORDEN , solo use el incorporado__mro__

es decir repr(YOUR_CLASS.__mro__)


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

salidas, EN ORDEN


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

Ahí tienes. La "mejor" respuesta en este momento, tiene 182 votos (mientras estoy escribiendo esto) pero esto es MUCHO más simple que algunos complicados para bucle, buscando bases una clase a la vez, sin mencionar cuando una clase extiende DOS o más padres clases Importar y usar inspectsolo nubla el alcance innecesariamente. Sinceramente, es una lástima que la gente no sepa usar solo los elementos integrados

¡Espero que esto ayude!

PyTis
fuente
@John Smith stackoverflow.com/users/139885/john-smith , espero que veas esta respuesta. Si te gusta, ¡házmelo saber con un voto a favor!
PyTis
1
De hecho, inspect.getmrosolo invoca __mro__objetos, como puede ver en github.com/python/cpython/blob/… . El uso getmroproduce un código más limpio y más legible. Aunque omitir una llamada de función es más rápido.
tna0y
9

Use bases si solo desea obtener los padres, use __mro__(como lo señaló @ naught101) para obtener el orden de resolución del método (para saber en qué orden se ejecutaron los init).

Bases (y primero obteniendo la clase para un objeto existente):

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

Para mro en versiones recientes de Python:

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

Obviamente, cuando ya tiene una definición de clase, puede invocarla __mro__directamente:

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

Si desea asegurarse de que se les llame supera todos , úselos en todos los niveles.

Mike Graham
fuente
Una vez que use super, debe usarlo en todos los niveles de todos modos, por lo que debe documentar su uso explícitamente. También es posible que desee saber que super no funciona en todas las clases ...
DasIch