将类名传递给字典(和解析顺序)

时间:2013-07-31 12:36:10

标签: python class parsing

我有一些代码如下:

class Action(object):
    ...

class SpecificAction1(Action):
    ...

class SpecificAction2(Action):
    ...

它们都在同一个文件中指定。在他们的规范之前,我想写一个如下所示的字典:

ACTIONS = {
    "SpecificAction1": SpecificAction1,
    "SpecificAction2": SpecificAction2
}

我的想法是,我可以简单地从其他模块导入ACTIONS字典,并让这一个字典成为动作的一个规范字符串表示(它们通过网络和我需要一些标识符的其他地方发送)。

是否有可能以与函数指针相同的方式执行这样的“类指针”?我的编辑抱怨说,在类定义之前声明字典之前,名称是未定义的 - 这是真的吗?

另外,如果以上情况可以,我可以这样做来实例化一个类:ACTIONS['SpecificAction2']()

2 个答案:

答案 0 :(得分:1)

是的,你可以这样做。 Python是一种动态语言,允许您这样做。但是,从ACTIONS dict开始,值是类的定义。如果您想通过网络提供它们,请将它们作为字符串传递并使用getattr

ACTIONS = {
    "SpecificAction1": 'SpecificAction1',
    "SpecificAction2": 'SpecificAction2'
}

他们导入包含定义的文件:

module = __import__('my_actions_module')
class_ = getattr(module,ACTIONS.get('SpecificAction1'))
instance = class_()

instance就是您所需要的。

答案 1 :(得分:1)

Python中的类是first-class citizens,即您可以像对待任何其他对象一样对待它们。从这个角度来看,你的构造完全没问题,除了你必须在文件的末尾定义ACTIONS字典(因为与其他语言不同,顺序在Python中很重要:否则会引发ReferenceError)。

还有更多。您可以使用一些元编程来简化这一过程。考虑一下(Python2.x,3.x中的语法略有不同):

ACTIONS = {}

class MyMeta(type):
    def __init__(cls, name, bases, nmspc):
        super(MyMeta, cls).__init__(name, bases, nmspc)
        if name != "Action": # <--- skip base class
            ACTIONS[name] = cls

class Action(object):
    __metaclass__ = MyMeta
    ...

class SpecificAction1(Action):
    ...

class SpecificAction2(Action):
    ...

它将自动使用从ACTIONS类继承的任何类填充Action字典(因为Action类具有MyMeta作为__metaclass__)。在这里阅读有关元编程的更多信息:

https://python-3-patterns-idioms-test.readthedocs.org/en/latest/Metaprogramming.html

至于ACTIONS['SpecificAction2']():是的,它会创建一个新的类实例,它是完全有效的代码。