Подтвердить что ты не робот

Python: найти все классы, которые наследуют от этого?

Есть ли способ в python запросить пространство имен для классов, которые наследуются от определенного класса? Учитывая класс widget, я хотел бы иметь возможность называть что-то вроде inheritors(widget), чтобы получить список всех моих видовых виджетов.

4b9b3361

Ответ 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()).