Como obter os pais de uma classe Python?

202

Como posso obter as classes pai de uma classe Python?

John Smith
fonte

Respostas:

233

Use o seguinte atributo:

cls.__bases__

Dos documentos :

A tupla de classes base de um objeto de classe.

Exemplo:

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

Outro exemplo:

>>> class A(object):
...   pass
... 
>>> class B(object):
...   pass
... 
>>> class C(A, B):
...   pass
... 
>>> C.__bases__
(<class '__main__.A'>, <class '__main__.B'>)
Ayman Hourieh
fonte
1
Para obter bases de um objeto instanciado, faça type(C()).__bases__o mencionado abaixo
citynorman
106

Se você deseja todos os ancestrais, e não apenas os ancestrais , use inspect.getmro :

import inspect
print inspect.getmro(cls)

De maneira útil, isso fornece a você todas as classes de ancestrais na "ordem de resolução do método" - isto é, a ordem na qual os ancestrais serão verificados ao resolver um método (ou, na verdade, qualquer outro atributo - métodos e outros atributos vivem no mesmo espaço de nome) afinal, em Python ;-).

Alex Martelli
fonte
34
Você também pode apenas usar cls.__mro__(pelo menos em Python 3.5)
naught101
@ naught101, plz transformá-lo em uma resposta completa. Eu quase senti falta e acho que muitas outras pessoas.
Shihab Shahriar Khan
14

As classes de novo estilo têm um método mro que você pode chamar, que retorna uma lista de classes pai na ordem de resolução do método.

DasIch
fonte
O que conta como uma classe de novo estilo? Parece que posso usar isso com os modelos do Django, mas qualquer coisa simplesmente herdada objectnão parece responder mro.
Brian Kung
1
considerando um objeto x, podemos obter a ordem de resolução do método com a chamada type(x).mro() que podemos considerar se xtiver ClassXcomo classe base: ClassX in type(x).mro()
648trindade
13

A maneira MAIS RÁPIDA , para ver todos os pais, e EM ORDEM , basta usar o__mro__

ie repr(YOUR_CLASS.__mro__)


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

saídas, EM ORDEM


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

Aí está. A "melhor" resposta no momento tem 182 votos (enquanto digito isso), mas isso é MUITO mais simples do que um loop for complicado, procurando nas bases uma classe de cada vez, sem mencionar quando uma classe estende DOIS ou mais pais Aulas. Importando e usandoinspect apenas obscurece o escopo desnecessariamente. Sinceramente, é uma pena que as pessoas não saibam usar apenas os embutidos

Eu espero que isso ajude!

PyTis
fonte
@John Smith stackoverflow.com/users/139885/john-smith , espero que você veja esta resposta. Se você gostou, por favor me avise com um voto positivo!
PyTis 26/03/19
1
De fato, inspect.getmrobasta chamar o __mro__objeto, como você pode ver em github.com/python/cpython/blob/… . Usar getmroproduz código mais limpo e mais legível. Embora pular uma chamada de função seja realmente mais rápido.
tna0y
9

Use bases se você quiser apenas obter os pais, use __mro__(como indicado por @ naught101) para obter a ordem de resolução do método (para saber em qual ordem os init foram executados).

Bases (e primeiro obtendo a classe para um objeto existente):

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

Para mro nas versões recentes do Python:

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

Obviamente, quando você já tem uma definição de classe, basta acessar __mro__diretamente:

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

Se você quiser garantir que todos sejam chamados, use superem todos os níveis.

Mike Graham
fonte
Depois de usar o super, você deve usá-lo em todos os níveis, e é por isso que você deve documentar seu uso explicitamente. Além disso, você pode querer saber que o super não funciona em todas as classes ...
DasIch