Wyświetlić wszystkie klasy bazowe w hierarchii danej klasy?

139

Biorąc pod uwagę klasę Foo(niezależnie od tego, czy jest to klasa w nowym stylu, czy nie), w jaki sposób można wygenerować wszystkie klasy podstawowe - w dowolnym miejscu w hierarchii dziedziczenia - issubclassz?

Sridhar Ratnakumar
źródło

Odpowiedzi:

198

inspect.getmro(cls)działa zarówno dla klas nowego, jak i starego stylu i zwraca to samo, co NewClass.mro(): lista klasy i wszystkich jej klas przodków, w kolejności używanej do rozwiązywania metod.

>>> class A(object):
>>>     pass
>>>
>>> class B(A):
>>>     pass
>>>
>>> import inspect
>>> inspect.getmro(B)
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
Jochen Ritzel
źródło
2
Nie działa dla klas pyobjc :( File "/Users/rbp/Projects/zzzzzzz/macmdtypes.py", wiersz 70, w trybie coerce print inspect.getmro (ścieżka) Plik "/System/Library/Frameworks/Python.framework/ Wersje / 2.7 / lib / python2.7 / inspect.py ", wiersz 348, w getmro searchbases (cls, result) File" /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect .py ”, wiersz 339, w _searchbases for base in cls .__ bases_ : AttributeError: Obiekt„ NSTaggedDate ”nie ma atrybutu„ __bases
rbp
18
@rbp Podejrzewam, że miałeś ten sam problem, co ja: inspect.getmro(obj)zamiast tego próbowałeś inspect.getmro(type(obj)).
prześlij
44

Zobacz __bases__właściwość dostępną w Pythonie class, która zawiera krotkę klas bazowych:

>>> def classlookup(cls):
...     c = list(cls.__bases__)
...     for base in c:
...         c.extend(classlookup(base))
...     return c
...
>>> class A: pass
...
>>> class B(A): pass
...
>>> class C(object, B): pass
...
>>> classlookup(C)
[<type 'object'>, <class __main__.B at 0x00AB7300>, <class __main__.A at 0x00A6D630>]
Crescent Fresh
źródło
5
Może to spowodować duplikaty. I właśnie dlatego dokumentacja getmrowyraźnie mówi: „Żadna klasa nie pojawia się więcej niż raz w tej krotce”?
Sridhar Ratnakumar
10
Uwaga, __bases__tylko jeden poziom w górę . (Jak sugeruje twoja rekurencyjna użyteczność, ale pobieżne spojrzenie na przykład może tego nie wykryć.)
Bob Stein
34

inspect.getclasstree()utworzy zagnieżdżoną listę klas i ich baz. Stosowanie:

inspect.getclasstree(inspect.getmro(IOError)) # Insert your Class instead of IOError.
Ned Batchelder
źródło
2
OOH nieźle. A dla jeszcze ładniejszego wydruku użyj pprint! python -c 'import inspect; from pprint import pprint as pp; pp(inspect.getclasstree(inspect.getmro(IOError)))'
pingwin 359
20

możesz użyć __bases__krotki obiektu klasy:

class A(object, B, C):
    def __init__(self):
       pass
print A.__bases__

Krotka zwrócona przez __bases__ma wszystkie swoje klasy bazowe.

Mam nadzieję, że to pomoże!

mandel
źródło
Jeśli twoje klasa dziedziczy z klasy, która dziedziczy z klasy, tylko pierwsza część łańcucha będzie jej__bases__
Boris
Prosty i przejrzysty bez importowania całego modułu dla pojedynczej funkcji.
Temperosa
8

W Pythonie 3.7 nie musisz importować inspect, type.mro da ci wynik.

>>> class A:
...   pass
... 
>>> class B(A):
...   pass
... 
>>> type.mro(B)
[<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
>>>

uwaga, że ​​w Pythonie 3.x każda klasa dziedziczy po podstawowej klasie obiektu.

Serjik
źródło
8

Zgodnie z dokumentacją Pythona możemy też po prostu użyć class.__mro__atrybutu lub class.mro()metody:

>>> class A:
...     pass
... 
>>> class B(A):
...     pass
... 
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
>>> A.__mro__
(<class '__main__.A'>, <class 'object'>)
>>> object.__mro__
(<class 'object'>,)
>>>
>>> B.mro()
[<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
>>> A.mro()
[<class '__main__.A'>, <class 'object'>]
>>> object.mro()
[<class 'object'>]
>>> A in B.mro()
True

YaOzI
źródło
2

Chociaż odpowiedź Jochena jest bardzo pomocna i poprawna, ponieważ hierarchię klas można uzyskać za pomocą metody .getmro () modułu inspect, należy również podkreślić, że hierarchia dziedziczenia w Pythonie jest następująca:

dawny:

class MyClass(YourClass):

Klasa dziedzicząca

  • Klasa dziecka
  • Klasy pochodnej
  • Podklasa

dawny:

class YourClass(Object):

Klasa dziedziczona

  • Klasa nadrzędna
  • Klasa podstawowa
  • Superklasa

Jedna klasa może dziedziczyć po innej - Klasa „atrybuty” jest dziedziczona - w szczególności jej metody są dziedziczone - oznacza to, że instancje klasy dziedziczącej (podrzędnej) mogą uzyskać dostęp przypisany do klasy dziedziczonej (nadrzędnej)

instancja -> klasa -> następnie dziedziczone klasy

za pomocą

import inspect
inspect.getmro(MyClass)

pokaże hierarchię w Pythonie.

Carson
źródło