我有一些代码如下:
class Action(object):
...
class SpecificAction1(Action):
...
class SpecificAction2(Action):
...
它们都在同一个文件中指定。在他们的规范之前,我想写一个如下所示的字典:
ACTIONS = {
"SpecificAction1": SpecificAction1,
"SpecificAction2": SpecificAction2
}
我的想法是,我可以简单地从其他模块导入ACTIONS字典,并让这一个字典成为动作的一个规范字符串表示(它们通过网络和我需要一些标识符的其他地方发送)。
是否有可能以与函数指针相同的方式执行这样的“类指针”?我的编辑抱怨说,在类定义之前声明字典之前,名称是未定义的 - 这是真的吗?
另外,如果以上情况可以,我可以这样做来实例化一个类:ACTIONS['SpecificAction2']()
?
答案 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']()
:是的,它会创建一个新的类实例,它是完全有效的代码。