Есть ли способ в python запросить пространство имен для классов, которые наследуются от определенного класса? Учитывая класс widget
, я хотел бы иметь возможность называть что-то вроде inheritors(widget)
, чтобы получить список всех моих видовых виджетов.
Python: найти все классы, которые наследуют от этого?
Ответ 1
Вы хотите использовать Widget.__subclasses__()
, чтобы получить список всех подклассов. Он ищет только прямые подклассы, хотя, если вы хотите их всех, вам придется немного поработать:
def inheritors(klass):
subclasses = set()
work = [klass]
while work:
parent = work.pop()
for child in parent.__subclasses__():
if child not in subclasses:
subclasses.add(child)
work.append(child)
return subclasses
N.B. Если вы используете Python 2.x, это работает только для классов нового стиля.
Ответ 2
Вы можете отслеживать наследование с помощью своего метакласса
import collections
class A(object):
class __metaclass__(type):
__inheritors__ = defaultdict(list)
def __new__(meta, name, bases, dct):
klass = type.__new__(meta, name, bases, dct)
for base in klass.mro()[1:-1]:
meta.__inheritors__[base].append(klass)
return klass
class B(A):
pass
class C(B):
pass
>>> A.__inheritors__
defaultdict(<type 'list'>, {<class '__main__.A'>: [<class '__main__.B'>, <class '__main__.C'>], <class '__main__.B'>: [<class '__main__.C'>]})
Все, что унаследовано от A
или его производные классы, будет отслеживаться. Вы получите полную карту наследования, когда будут загружены все модули в вашем приложении.
Ответ 3
# return list of tuples (objclass, name) containing all subclasses in callers' module
def FindAllSubclasses(classType):
import sys, inspect
subclasses = []
callers_module = sys._getframe(1).f_globals['__name__']
classes = inspect.getmembers(sys.modules[callers_module], inspect.isclass)
for name, obj in classes:
if (obj is not classType) and (classType in inspect.getmro(obj)):
subclasses.append((obj, name))
return subclasses
Ответ 4
Вам нужно пройти через все объекты в глобальном пространстве имен (globals()) и проверить, является ли связанный объект/класс подклассом другого класса (проверьте документы Python для issubclass()).