解决方案
这行得通:
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>]