Поиск всех подклассов определенного класса в Python
Пройдите тест, узнайте какой профессии подходите
Быстрый ответ
Cls = globals()['MyClass'] # Замените 'MyClass' на ту часть, которая соответствует названию вашего класса
subclasses = Cls.__subclasses__()
Для поиска подклассов для 'MyClass'
, выполните следующие действия:
Получите экземпляр класса с помощью функции
globals()
:Cls = globals()['MyClass']
Определите непосредственных наследников класса с помощью метода
__subclasses__()
:subclasses = Cls.__subclasses__()
Продолжайте исследование с использованием рекурсии
Для изучения всех уровней наследования, включая прямых наследников и более дальних потомков класса, примените следующий процесс:
def find_all_kids(cls):
"""Находим всех потомков на всех уровнях наследования."""
for kiddo in cls.__subclasses__():
yield kiddo
yield from find_all_kids(kiddo) # Рекурсия здесь играет важную роль
# Пример использования
all_kids = list(find_all_kids(Cls)) # Собираем всю многочисленную родню
Импортируйте для нахождения большего количества наследников
Метод __subclasses__()
обнаружит лишь те подклассы, которые были импортированы. Чтобы выявить больше "родственников", следуйте двум шагам:
- Импортируйте известные модули.
Для отыскания неизвестных подклассов воспользуйтесь
importlib
:import importlib module = importlib.import_module('module_name') # Здесь модуль, в котором может "проживать" ваш класс Cls = getattr(module, 'MyClass') # Укажите имя вашего класса
__init_subclass__
для мониторинга появления новых потомков
Метод __init_subclass__
дает возможность в Python 3.6+ наблюдать за созданием новых подклассов и добавлять их в список:
class Base:
kids = [] # Здесь будем хранить подклассы
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
Base.kids.append(cls) # Как только найдено новое ниспоследование, добавляем его в список
Визуализация
Продемонстрируем поиск возможных "родственников" при помощи веселой и условной графической семейной диаграммы:
Семейное Древо (🌳): [Класс-Прародитель (💼)] / \ Класс-Родитель (📚) Класс-Дядя (🎩) / \ Класс-Ребёнок (🎓) Класс-Брат/Сестра (🏅)
Результаты поиска в рамках этой родословной:
import inspect
descendant_classes = [
cls for name, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass)
if issubclass(cls, globals()['Grandparent Class']) # Здесь указатель на прародителя
]
У нас получилось собрать таких участников на семейном собрании: [📚, 🎩, 🎓, 🏅]
Продвинутые методы поиска
Отточите свои навыки до нового уровня с помощью следующих подходов:
- Организовывайте "семейные встречи", используя методы класса.
- Управляйте наследованием, переопределяя
__subclasses__
в__init_subclass__
. - Расширяйте количество подклассов, как настоящий проектировщик.
- Старайтесь избегать использования
eval
, это опасно, как приглашать на праздник эксцентричного дядюшку.
Важные нюансы
Не забывайте, что даже в самой привычной обстановке могут возникнуть посторонние эффекты. Вот что стоит держать в уме:
- В "семейный круг" включены классы, находящиеся в текущем пространстве имен.
- Учитывайте динамические импорты для тех, кто может пропустить мероприятие.
- Опираясь на
vars()
, вы можете собрать под окнами весь квартал.
Полезные материалы
- inspect — Инспекция живых объектов Python 3
- Метод разрешения заказов в Python – GeeksforGeeks
- Экземпляры, методы класса и статические методы – Real Python
- abc — Абстрактные базовые классы в Python 3
- Понимание метаклассов в Python | Ionel's Codelog
- Как найти все подклассы класса по его наименованию? – Stack Overflow
- Python: как выявить все классы, унаследованные от данного? – Stack Overflow