Python создает все классы внутри модуля

Я работаю над текстовой приключенческой игрой и у меня есть модуль, в котором есть все классы действий, например Move(Action), Look(Action), Мне нужен метод создания экземпляров всех классов в модуле, которые являются подклассом Action Класс в список, как это:

actions = [Move(), Look()]

Есть ли способ сделать это без необходимости индивидуально создавать экземпляры классов, вводя их имена?

2 ответа

Решение

Решение

Это работает:

class Action:
    pass

class Move(Action):
    pass

class Look(Action):
    pass


actions = []
global_objs = list(globals().items())

for name, obj in global_objs:
    if obj is not Action and isinstance(obj, type) and issubclass(obj, Action):
        actions.append(obj())
print(actions)

печатает:

[<__main__.Move object at 0x101916ba8>, <__main__.Look object at 0x101916be0>]

меры

Сначала мы получаем все имена объекта в текущем модуле:

global_objs = list(globals().items())

Нам нужно преобразовать в список, потому что в Python 3 items() вернуть объект dictview, который отражает изменения в нижележащем словаре. Поскольку мы работаем в одном и том же модуле, определение новых объектов изменит этот словарь. Преобразование в список решает эту проблему.

Далее мы проходим все объекты. Есть три условия, которые они должны выполнить, чтобы быть подклассом Action:

  1. obj is not Action- Поскольку Action это подкласс сам по себе, мы должны отфильтровать его.

  2. isinstance(obj, type) - Объект должен быть классом. В противном случае тест под 3. был бы невозможен.

  3. issubclass(obj, Action) - Наконец, мы можем сделать наш тест подкласса.

Теперь мы можем создавать экземпляры всех отфильтрованных классов и добавлять их в наш список:

actions.append(obj())

Более короткая версия

Если вы уверены, что все классы определены в одном модуле или вам нужны все подклассы, которые распределены по нескольким модулям, это будет намного короче:

>>> actions = [obj() for obj in Action.__subclasses__()]
>>> actions
[<__main__.Move at 0x10fc14fd0>, <__main__.Look at 0x10fc14668>]
from other_module import Action

def is_action_class(var):
    return var != Action and type(var) == type and issubclass(var, Action)

classes = []    

for attr in dir(my_module):
    var = getattr(my_module, attr)
    if is_action_class(var):
        classes.append(var)
instances = [c() for c in classes]
Другие вопросы по тегам