Перечислить все базовые классы в иерархии данного класса?

Ответы:

196

inspect.getmro(cls)работает как для новых, так и для старых классов и возвращает то же самое, что и NewClass.mro(): список класса и всех его классов-предков в порядке, используемом для разрешения метода.

>>> class A(object):
>>>     pass
>>>
>>> class B(A):
>>>     pass
>>>
>>> import inspect
>>> inspect.getmro(B)
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
Йохен Ритцель
источник
2
Не работает для классов pyobjc :( Файл "/Users/rbp/Projects/zzzzzzz/macmdtypes.py", строка 70, в принудительной печати файл inspect.getmro (путь) "/System/Library/Frameworks/Python.framework/ Версии / 2.7 / lib / python2.7 / inspect.py ", строка 348, в файле поисковых баз getmro (cls, result)" /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect .py ", строка 339, в _searchbases для базы в cls .__ base_ : AttributeError: объект ' NSTaggedDate' не имеет атрибута '__bases '
rbp
17
@rbp Я подозреваю, что у вас была та же проблема, с которой я столкнулся: вы пытались сделать inspect.getmro(obj)вместо inspect.getmro(type(obj)).
esmit 09
44

См. __bases__Свойство, доступное на питоне class, которое содержит кортеж базовых классов:

>>> 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>]
Свежий полумесяц
источник
5
Это может привести к дублированию. И поэтому в документации для getmroявно сказано: «Ни один класс не появляется в этом кортеже более одного раза»?
Шридхар Ратнакумар,
10
Осторожно, __bases__поднимается только на один уровень . (Как и предполагает ваша рекурсивная утилита, но беглый взгляд на пример может не уловить этого.)
Боб Стейн,
32

inspect.getclasstree()создаст вложенный список классов и их баз. Использование:

inspect.getclasstree(inspect.getmro(IOError)) # Insert your Class instead of IOError.
Нед Бэтчелдер
источник
1
О, мило. А для еще более качественного вывода используйте pprint! python -c 'import inspect; from pprint import pprint as pp; pp(inspect.getclasstree(inspect.getmro(IOError)))'
penguin359
20

вы можете использовать __bases__кортеж объекта класса:

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

Кортеж, возвращаемый функцией, __bases__имеет все свои базовые классы.

Надеюсь, поможет!

Мандель
источник
Если ваш класс наследуется от класса, который наследуется от класса, в нем будет только первая часть цепочки__bases__
Борис
Просто и чисто, без импорта целого модуля для одной функции.
Temperosa,
8

В python 3.7 вам не нужно импортировать inspect, результат выдаст type.mro.

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

Обратите внимание, что в python 3.x каждый класс наследуется от класса базового объекта.

Сержик
источник
8

Согласно документу Python , мы также можем просто использовать class.__mro__атрибут или class.mro()метод:

>>> 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
источник
2

Хотя ответ Йохена очень полезен и верен, поскольку вы можете получить иерархию классов с помощью метода .getmro () модуля inspect, также важно подчеркнуть, что иерархия наследования Python выглядит следующим образом:

например:

class MyClass(YourClass):

Наследующий класс

  • Детский класс
  • Производный класс
  • Подкласс

например:

class YourClass(Object):

Унаследованный класс

  • Родительский класс
  • Базовый класс
  • Superclass

Один класс может наследовать от другого - атрибуты класса наследуются - в частности, его методы наследуются - это означает, что экземпляры наследующего (дочернего) класса могут получить доступ к атрибутам унаследованного (родительского) класса.

экземпляр -> класс -> затем унаследованные классы

с помощью

import inspect
inspect.getmro(MyClass)

покажет вам иерархию в Python.

Carson
источник