【问题标题】:Python Instantiate All Classes Within a Module [duplicate]Python实例化模块中的所有类[重复]
【发布时间】:2016-04-05 22:09:33
【问题描述】:

我正在开发一个基于文本的冒险游戏,并且有一个包含所有动作类的模块,例如Move(Action),Look(Action)。我需要一种方法,将模块中作为Action 类的子类的所有类实例化为如下列表:

actions = [Move(), Look()]

有没有一种方法可以做到这一点,而不必通过键入它们的名称来单独实例化这些类?

【问题讨论】:

  • 我相信您可以从那里找出如何将它们全部实例化!

标签: python python-3.5 adventure


【解决方案1】:

解决方案

这行得通:

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>]

【讨论】:

  • for obj in Action.__subclasses__() 会帮你省很多事...
  • @jonrsharpe 好点。但它会找到所有子类;不仅是模块中的这些。仍然需要过滤这些。
  • 好点,但 OP 确实说它们都在一个模块中
  • 添加了一个变体。确实短得多。
【解决方案2】:
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]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-17
    • 2019-01-13
    • 1970-01-01
    • 2017-02-09
    • 2020-06-18
    • 2021-07-04
    • 2019-12-08
    • 1970-01-01
    相关资源
    最近更新 更多