Wie bekomme ich die Eltern einer Python-Klasse?

201

Wie kann ich die übergeordneten Klassen einer Python-Klasse abrufen?

John Smith
quelle

Antworten:

232

Verwenden Sie das folgende Attribut:

cls.__bases__

Aus den Dokumenten :

Das Tupel der Basisklassen eines Klassenobjekts.

Beispiel:

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

Ein anderes Beispiel:

>>> class A(object):
...   pass
... 
>>> class B(object):
...   pass
... 
>>> class C(A, B):
...   pass
... 
>>> C.__bases__
(<class '__main__.A'>, <class '__main__.B'>)
Ayman Hourieh
quelle
1
Um die Basis eines instanziierten Objekts zu erhalten, gehen Sie type(C()).__bases__wie unten beschrieben vor
citynorman
105

Wenn Sie alle Vorfahren und nicht nur die unmittelbaren möchten , verwenden Sie inspect.getmro :

import inspect
print inspect.getmro(cls)

Auf diese Weise erhalten Sie alle Vorfahrenklassen in der "Reihenfolge der Methodenauflösung", dh in der Reihenfolge, in der die Vorfahren beim Auflösen einer Methode überprüft werden (oder tatsächlich alle anderen Attribute - Methoden und andere Attribute befinden sich im selben Namespace Immerhin in Python ;-).

Alex Martelli
quelle
32
Sie können auch nur verwenden cls.__mro__(zumindest in Python 3.5)
naught101
@ naught101, bitte verwandeln Sie es in eine vollständige Antwort. Ich habe es fast verpasst, und ich denke, viele andere Leute auch.
Shihab Shahriar Khan
14

Klassen neuen Stils verfügen über eine von Ihnen aufrufbare mro-Methode, die eine Liste der übergeordneten Klassen in der Reihenfolge der Methodenauflösung zurückgibt.

DasIch
quelle
Was zählt als neue Klasse? Es scheint, dass ich dies mit Django-Modellen verwenden kann, aber alles, was einfach von etwas erbt, objectscheint nicht darauf zu reagieren mro.
Brian Kung
1
ein Objekt unter Berücksichtigung x, können wir die Methode Auflösung , um mit dem Anruf bekommen type(x).mro() wir , wenn betrachten können xhat ClassXmit als Basisklasse: ClassX in type(x).mro()
648trindade
13

Der SCHNELLSTE Weg, um alle Eltern zu sehen, und IN ORDNUNG verwenden Sie einfach die eingebaute__mro__

dh repr(YOUR_CLASS.__mro__)


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

Ausgänge, IN BESTELLUNG


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

Hier hast du es. Die „beste“ Antwort jetzt hat 182 Stimmen (wie ich dies tippe) , aber das ist so viel einfacher als einig für Schleife gefaltet, Blick in den Basen eine Klasse zu einem Zeitpunkt, nicht zu erwähnen , wenn eine Klasse erweitert zwei oder mehr Eltern Klassen. Durch das Importieren und Verwenden von inspectClouds wird der Bereich unnötig erweitert. Es ist ehrlich gesagt eine Schande, dass die Leute nicht wissen, nur die eingebauten Geräte zu verwenden

Ich hoffe das hilft!

PyTis
quelle
@ John Smith stackoverflow.com/users/139885/john-smith , ich hoffe du siehst diese Antwort. Wenn es Ihnen gefällt, lassen Sie es mich bitte mit einem Upvote wissen!
PyTis
1
In der Tat, inspect.getmronur Anrufe __mro__auf dem Objekt, wie Sie sehen können in github.com/python/cpython/blob/... . Die Verwendung getmroerzeugt saubereren und besser lesbaren Code. Das Überspringen eines Funktionsaufrufs ist zwar schneller.
tna0y
9

Verwenden Sie Basen, wenn Sie nur die Eltern erhalten möchten, und verwenden Sie __mro__(wie von @ naught101 hervorgehoben), um die Reihenfolge der Methodenauflösung abzurufen (um zu wissen, in welcher Reihenfolge die Inits ausgeführt wurden).

Grundlagen (und zuerst die Klasse für ein vorhandenes Objekt abrufen):

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

Für mro in neueren Python-Versionen:

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

Wenn Sie bereits eine Klassendefinition haben, können Sie diese natürlich direkt aufrufen __mro__:

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

Wenn Sie sicherstellen möchten, dass alle aufgerufen werden, verwenden Sie sie superauf allen Ebenen.

Mike Graham
quelle
Sobald Sie Super verwenden, müssen Sie es ohnehin in allen Ebenen verwenden, weshalb Sie die Verwendung explizit dokumentieren sollten. Vielleicht möchten Sie auch wissen, dass Super nicht in jeder Klasse
funktioniert