尝试基于字符串值实例化一个类并且......失败.parser下面的对象是a dict,在这个例子中假设我们有一个被调用foo,这里parser['name']是'foo':
obj = parser['name']()
Run Code Online (Sandbox Code Playgroud)
失败,屈服TypeError: 'str' object is not callable.但是,因为我有:
class foo:
def __init__(self():
print 'Hello'
Run Code Online (Sandbox Code Playgroud)
如果我这样做obj = foo()它工作正常并创建正确的对象.此外,呼叫obj = type(parser['name'])()不起作用.
怎么解决这个?更新:我真的不想使用映射系统:这些类的名称是定义INI文件,并以这种方式解析,所以它们将是字符串..
Ign*_*ams 12
classmap = {
'foo': foo
}
obj = classmap[parser['name']]()
Run Code Online (Sandbox Code Playgroud)
小智 11
正如回答:
Python动态类名
如果您知道定义类的模块,则有一种更简单的方法,例如:
getattr(my_module, my_class_name)()
Run Code Online (Sandbox Code Playgroud)
不要使用字符串:
parser = {}
class foo:
pass
parser['foo'] = foo
obj = parser['foo']()
Run Code Online (Sandbox Code Playgroud)
您可以使用存储已知类字典的元类:
# a metaclass
class Registry(type):
# store all the types we know
registered = {}
def __new__(cls, name, bases, attrs):
# create the new type
newtype = super(Registry, cls).__new__(cls, name, bases, attrs)
# store it
cls.registered[name] = newtype
return newtype
@classmethod
def class_by_name(cls, name):
# get a class from the registerd classes
return cls.registered[name]
# arbitrary base class for every class that should be in the Register
class Registered(object):
__metaclass__ = Registry
# some classes
class Foo(Registered):
pass
class Bar(Foo):
pass
# get the class object:
print Registry.class_by_name('Foo') # <class '__main__.Foo'>
# it can be instanciated too ofc:
print Registry.class_by_name('Bar')() # <__main__.Bar object at 0x01F0F9F0>
Run Code Online (Sandbox Code Playgroud)
但并不是每个人都理解元类,因此您可能希望避免使用它们以防止任何混淆。它们对于这样的事情很有用,但是正如您从其他答案中看到的那样,还有很多其他方法可以做到这一点。
小智 5
内置函数type(name, bases, dict)是动态构造类的正确方法——特别是当给定类名字符串时。请参阅此处的文档:http ://docs.python.org/library/functions.html#type
在您的特定示例中,它可能如下所示:
>>> def init(self):
... print 'Hello'
...
>>> Foo = type('Foo', (object,), {'__init__': init})
>>> foo = Foo()
Hello
Run Code Online (Sandbox Code Playgroud)