Come ottenere i genitori di una classe Python?


202

Come posso ottenere le classi genitore di una classe Python?

Risposte:


233

Usa il seguente attributo:

cls.__bases__

Dai documenti :

La tupla di classi base di un oggetto classe.

Esempio:

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

Un altro esempio:

>>> class A(object):
...   pass
... 
>>> class B(object):
...   pass
... 
>>> class C(A, B):
...   pass
... 
>>> C.__bases__
(<class '__main__.A'>, <class '__main__.B'>)

1
Per ottenere le basi di un oggetto istanziato, fai type(C()).__bases__come indicato più avanti
citynorman,

106

Se vuoi tutti gli antenati anziché solo quelli immediati, usa inspect.getmro :

import inspect
print inspect.getmro(cls)

Utilmente, questo ti dà tutte le classi di antenati nell '"ordine di risoluzione del metodo" - cioè l'ordine in cui gli antenati verranno controllati quando si risolve un metodo (o, in realtà, qualsiasi altro attributo - metodi e altri attributi vivono nello stesso spazio dei nomi in Python, dopo tutto ;-).


34
Puoi anche usare cls.__mro__(almeno in Python 3.5)
nought101

@ naught101, per favore trasformalo in una risposta completa. Quasi mi mancava, e così sarà, penso a molte altre persone.
Shihab Shahriar Khan,

14

Le classi di nuovo stile hanno un metodo mro che puoi chiamare che restituisce un elenco di classi principali in ordine di risoluzione del metodo.


Cosa conta come una classe di nuovo stile? Sembra che io possa usarlo con i modelli Django, ma qualsiasi cosa che semplicemente eredita objectnon sembra rispondere mro.
Brian Kung,

1
considerando un oggetto x, possiamo ottenere l'ordine di risoluzione del metodo con la chiamata type(x).mro() che possiamo considerare se xha ClassXcome classe base con: ClassX in type(x).mro()
648trindade il

13

Il modo PIÙ VELOCE , per vedere tutti i genitori, e IN ORDINE , basta usare il built-in__mro__

vale a dire repr(YOUR_CLASS.__mro__)


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

uscite, IN ORDINE


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

Ecco qua. La risposta "migliore" in questo momento, ha 182 voti (mentre lo sto scrivendo) ma è molto più semplice di un ciclo contorto, che esamina le basi una classe alla volta, per non parlare quando una classe estende DUE o più genitori classi. L'importazione e l'utilizzo di inspectcloud semplicemente non è necessario. Onestamente è un peccato che la gente non sappia usare solo i built-in

Spero che aiuti!


@ John Smith stackoverflow.com/users/139885/john-smith , spero di vedere questa risposta. Se ti piace, fammi sapere con un voto!
PyTis il

1
In effetti, inspect.getmrochiama semplicemente __mro__l'oggetto, come puoi vedere in github.com/python/cpython/blob/… . L'utilizzo getmroproduce un codice più pulito e più leggibile. Anche se saltare una chiamata di funzione è davvero più veloce.
tna0y,

9

Usa le basi se vuoi solo ottenere i genitori, usa __mro__ (come sottolineato da @ naught101) per ottenere l'ordine di risoluzione del metodo (in modo da sapere in quale ordine sono stati eseguiti gli init).

Basi (e prima ottenere la classe per un oggetto esistente):

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

Per mro nelle recenti versioni di Python:

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

Ovviamente, quando hai già una definizione di classe, puoi semplicemente chiamarla __mro__direttamente:

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

3

Se vuoi assicurarti che vengano chiamati tutti, usa supera tutti i livelli.


Una volta che usi super, devi comunque usarlo a tutti i livelli, motivo per cui dovresti documentarlo esplicitamente. Inoltre potresti voler sapere che il super non funziona su tutte le lezioni ...
DasIch
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.