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
:
obj is not Action
- ПосколькуAction
это подкласс сам по себе, мы должны отфильтровать его.isinstance(obj, type)
- Объект должен быть классом. В противном случае тест под 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]