Jak zdobyć rodziców klasy Python?

202

Jak mogę uzyskać klasy nadrzędne klasy Python?

John Smith
źródło

Odpowiedzi:

233

Użyj następującego atrybutu:

cls.__bases__

Z dokumentów :

Krotka klas podstawowych obiektu klasy.

Przykład:

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

Inny przykład:

>>> class A(object):
...   pass
... 
>>> class B(object):
...   pass
... 
>>> class C(A, B):
...   pass
... 
>>> C.__bases__
(<class '__main__.A'>, <class '__main__.B'>)
Ayman Hourieh
źródło
1
Aby uzyskać podstawy obiektu instancji, wykonaj czynności type(C()).__bases__opisane poniżej
citynorman
106

Jeśli chcesz wszystkich przodków, a nie tylko bezpośrednich, użyj inspect.getmro :

import inspect
print inspect.getmro(cls)

Przydatnie, daje to wszystkie klasy przodków w „kolejności rozpoznawania metod” - tj. W kolejności, w której przodkowie będą sprawdzani podczas rozwiązywania metody (lub w rzeczywistości dowolnego innego atrybutu - metody i inne atrybuty żyją w tej samej przestrzeni nazw w końcu w Pythonie ;-).

Alex Martelli
źródło
34
Możesz także użyć cls.__mro__(przynajmniej w Pythonie 3.5)
naught101 16.01.17
@ naught101, plz zmień to w pełną odpowiedź. Prawie za tym tęskniłem i podobnie myślę, że wielu innych ludzi.
Shihab Shahriar Khan
14

Klasy w nowym stylu mają metodę mro, którą można wywołać, która zwraca listę klas nadrzędnych w kolejności rozwiązywania metod.

Dasich
źródło
Co liczy się jako klasa w nowym stylu? Wydaje się, że mogę tego używać z modelami Django, ale objectwydaje się , że nic po prostu dziedziczącego po nie odpowiada mro.
Brian Kung,
1
rozważając obiekt x, możemy uzyskać kolejność rozwiązywania metod z wywołaniem, type(x).mro() które możemy rozważyć, jeśli xma ClassXjako klasę podstawową z: ClassX in type(x).mro()
648trindade
13

Najszybszy sposób, aby zobaczyć wszystkich rodziców i NA ZAMÓWIENIE , wystarczy użyć wbudowanego__mro__

to znaczy repr(YOUR_CLASS.__mro__)


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

wyjścia, W ZAMÓWIENIU


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

Masz to. „Najlepsza” odpowiedź ma teraz 182 głosy (jak to piszę), ale jest to TAK O wiele prostsze niż niektóre skomplikowane pętle, patrząc na podstawy jednej klasy na raz, nie wspominając o tym, kiedy klasa rozszerza DWA lub więcej rodziców zajęcia inspectNiepotrzebne importowanie i używanie tylko chmur powoduje, że zakres jest niepotrzebny. Szkoda, że ​​ludzie nie wiedzą, jak korzystać z wbudowanych funkcji

Mam nadzieję, że to pomoże!

PyTis
źródło
@John Smith stackoverflow.com/users/139885/john-smith , mam nadzieję, że zobaczysz tę odpowiedź. Jeśli Ci się spodoba, daj mi znać z entuzjazmem!
PyTis
1
W rzeczywistości inspect.getmropo prostu wywołuje __mro__obiekt, jak widać na github.com/python/cpython/blob/… . Użycie getmrotworzy czystszy i bardziej czytelny kod. Chociaż pomijanie wywołania funkcji jest rzeczywiście szybsze.
tna0y
9

Użyj baz, jeśli chcesz tylko zdobyć rodziców, użyj __mro__(jak wskazał @ naught101), aby uzyskać kolejność rozwiązywania metod (aby wiedzieć, w jakiej kolejności zostały wykonane init).

Podstawy (i pierwsze uzyskanie klasy dla istniejącego obiektu):

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

W przypadku mro w najnowszych wersjach języka Python:

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

Oczywiście, gdy masz już definicję klasy, możesz po prostu wywołać __mro__ją bezpośrednio:

>>> class A(): pass
>>> A.__mro__
(__main__.A, object)
PascalVKooten
źródło
3

Jeśli chcesz mieć pewność, że wszystkie zostaną wywołane, użyj superna wszystkich poziomach.

Mike Graham
źródło
Kiedy już użyjesz super, musisz użyć go na wszystkich poziomach, dlatego powinieneś udokumentować jego użycie jawnie. Możesz także chcieć wiedzieć, że super nie działa na każdej klasie ...
DasIch