Python实例化模块中的所有类[duplicate]

时间:2022-09-25 11:54:46

This question already has an answer here:

这个问题已经有了答案:

I am working on a text-based adventure game and have a module that has all of the action classes, e.g. Move(Action), Look(Action). I need a method of instantiating all of the classes in the module that are a subclass of the Action class into a list like this:

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

actions = [Move(), Look()]

Is there a way of doing this without having to individually instantiate the classes by typing their names?

是否有一种方法可以做到这一点,而不必通过输入类名来单独实例化类?

2 个解决方案

#1


7  

Solution

This works:

如此:

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)

prints:

打印:

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

Steps

First, we get all names an an object in the current module:

首先,我们在当前模块中获得一个对象的所有名称:

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

We need to convert into a list because in Python 3 items() return a dictview object that reflects changes in the underlaying dictionary. Since we work in the same module, defining new objects will change this dictionary. Converting into a list solves this problem.

我们需要将其转换为一个列表,因为在Python 3 items()中,返回一个会反映底层字典变化的dictview对象。由于我们在同一个模块中工作,定义新的对象将会改变这个字典。转换成列表可以解决这个问题。

Next, we go through all objects. There are three conditions they need to fulfill to be subclass of Action:

接下来,我们遍历所有对象。他们需要满足以下三个条件:

  1. obj is not Action- Since Action is a subclass of itself, we need filter it out.

    obj不是动作,因为动作本身是一个子类,我们需要过滤它。

  2. isinstance(obj, type) - The object has to be a class. Otherwise, the test under 3. would not be possible.

    isinstance(obj, type)——对象必须是一个类。否则,测试在3以下。是不可能的。

  3. issubclass(obj, Action) - Finally, we can do our subclass test.

    issubclass(obj, Action)——最后,我们可以做子类测试。

Now we can make instances of all filtered classes and append them to our list:

现在我们可以将所有经过过滤的类的实例添加到我们的列表中:

actions.append(obj())

Shorter version

If you are sure all classes are defined in one module or you even want all subclasses that are distributed over several modules, this would be much shorter:

如果您确定所有的类都是在一个模块中定义的,或者您甚至希望所有的子类都分布在多个模块中,那么这将会更短:

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

#2


1  

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]

#1


7  

Solution

This works:

如此:

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)

prints:

打印:

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

Steps

First, we get all names an an object in the current module:

首先,我们在当前模块中获得一个对象的所有名称:

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

We need to convert into a list because in Python 3 items() return a dictview object that reflects changes in the underlaying dictionary. Since we work in the same module, defining new objects will change this dictionary. Converting into a list solves this problem.

我们需要将其转换为一个列表,因为在Python 3 items()中,返回一个会反映底层字典变化的dictview对象。由于我们在同一个模块中工作,定义新的对象将会改变这个字典。转换成列表可以解决这个问题。

Next, we go through all objects. There are three conditions they need to fulfill to be subclass of Action:

接下来,我们遍历所有对象。他们需要满足以下三个条件:

  1. obj is not Action- Since Action is a subclass of itself, we need filter it out.

    obj不是动作,因为动作本身是一个子类,我们需要过滤它。

  2. isinstance(obj, type) - The object has to be a class. Otherwise, the test under 3. would not be possible.

    isinstance(obj, type)——对象必须是一个类。否则,测试在3以下。是不可能的。

  3. issubclass(obj, Action) - Finally, we can do our subclass test.

    issubclass(obj, Action)——最后,我们可以做子类测试。

Now we can make instances of all filtered classes and append them to our list:

现在我们可以将所有经过过滤的类的实例添加到我们的列表中:

actions.append(obj())

Shorter version

If you are sure all classes are defined in one module or you even want all subclasses that are distributed over several modules, this would be much shorter:

如果您确定所有的类都是在一个模块中定义的,或者您甚至希望所有的子类都分布在多个模块中,那么这将会更短:

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

#2


1  

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]