python动态类名

Wel*_*lls 6 python

尝试基于字符串值实例化一个类并且......失败.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)

  • 因此,如果您使用工厂模式,则必须在代码中的某个位置映射可以返回的所有可能的类? (2认同)

小智 11

正如回答:
Python动态类名

如果您知道定义类的模块,则有一种更简单的方法,例如:

getattr(my_module, my_class_name)()
Run Code Online (Sandbox Code Playgroud)


Fal*_*rri 6

不要使用字符串:

parser = {}

class foo:
    pass


parser['foo'] = foo

obj = parser['foo']()
Run Code Online (Sandbox Code Playgroud)


Joc*_*zel 6

您可以使用存储已知类字典的元类:

# 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)