在Python中使用变量作为类名?

45 人关注

我想知道如何在Python中为对象和函数名使用变量。在PHP中,你可以这样做。

$className = "MyClass";
$newObject = new $className();

你在Python中是如何做这种事情的?或者,我是不是完全没有理解Python的一些根本区别,如果是的话,是什么呢?

5 个评论
TimB
我很想听听你为什么要这样做 -- 我想可能有一种更符合Pythonic的方法,不需要变量类名。
"我是不是完全没有领会到与Python的一些根本区别,如果是的话,是什么呢?" 有可能。 你为什么要使用上面的例子那样的代码? 请提供一个更大的例子,提供一些背景。
有意思,但我同意TimB的观点,我想听听这个的用例。
在Python中没有变量,只有名字。
在最近的一个案例中,我实现了一个类的两个不同的子类。它们对相同的一般工作有类似的不同实现,而且它们的API大致相同。我猜这是一种策略模式?总之,我想根据上下文动态地使用一个或另一个。
python
dynamic-typing
Sam McAfee
Sam McAfee
发布于 2008-10-22
6 个回答
Jason Baker
Jason Baker
发布于 2022-04-12
已采纳
0 人赞同

假设some_module有一个名为 "class_name "的类。

import some_module
klass = getattr(some_module, "class_name")
some_object = klass()

我应该注意,你在这里应该小心:如果字符串来自于用户,将字符串变成代码会很危险,所以在这种情况下你应该注意安全。 :)

还有一种方法(假设我们仍然在使用 "class_name")。

class_lookup = { 'class_name' : class_name }
some_object = class_lookup['class_name']()  #call the object once we've pulled it out of the dict

后一种方法可能是最安全的方法,所以如果可能的话,你应该使用这种方法。

非常好,我正在为动态类和动态字段创建一个手柄。我做了 classes = {'class1': Class1, 'class2': Class2,...} 。现在我可以用 myob = classes['<class_name'].objects.get(id=<obj_id>) 来获得这个对象。
伟大的,简单的技巧。在我发现这个之前,我已经被烦扰了2个小时。谢谢。
Greg Hewgill
Greg Hewgill
发布于 2022-04-12
0 人赞同

In Python,

className = MyClass
newObject = className()

第一行使变量className指代与MyClass相同的东西。然后下一行通过className变量调用MyClass构造函数。

作为一个具体的例子。

>>> className = list
>>> newObject = className()
>>> newObject

(在Python中,listlist类的构造函数。)

不同的是,在 PHP 中,你用一个字符串来表示你想引用的类的名字,而在 Python 中,你可以直接引用同一个类。如果你must使用一个字符串(例如,如果类的名称是动态创建的),那么你将需要使用其他技术。

被降权了,因为你的方案与问题中的方案不一致。他要找的是用一个字符串实例化一个类。
请遵守PEP8。使用混合大小写的名字感觉有点违背SO所代表的价值观。
Matt
同意第一条评论,这对存储在变量中的类名不起作用。
Mr.L
它对OP有效,这就是为什么他接受了这个答案@Matt 。对我来说也是如此。
@reggie,我以为他问的是一个字符串,我想提出问题的人可能也用Greg Hewgill的方案解决了问题。因为,我们想使用的所有类都必须已经存在,他可以把它们导入到一个名字中去使用,而不是一个随机的字符串!
coleifer
coleifer
发布于 2022-04-12
0 人赞同

如果你需要在Python中创建一个动态类(即一个名字是变量的类),你可以使用type(),它需要3个参数。 name, bases, attrs

>>> class_name = 'MyClass'
>>> klass = type(class_name, (object,), {'msg': 'foobarbaz'})
<class '__main__.MyClass'>
>>> inst = klass()
>>> inst.msg
foobarbaz
  • Note however, that this does not 'instantiate' the object (i.e. does not call constructors etc. It creates a new(!) class with the same name.
  • TimB
    TimB
    发布于 2022-04-12
    0 人赞同

    如果你有这个。

    class MyClass:
        def __init__(self):
            print "MyClass"
    

    然后你通常这样做。

    >>> x = MyClass()
    MyClass
    

    但你也可以这样做,我想你问的就是这个。

    >>> a = "MyClass"
    >>> y = eval(a)()
    MyClass
    

    但是,要非常小心你从哪里得到使用 "eval() "的字符串 -- 如果它来自用户,你基本上是在创造一个巨大的安全漏洞。

    更新:如coleifer的答案所示,使用type()远远优于这个解决方案。

    ddaa
    OMG,不!eval函数是邪恶的。请不要使用它。
    Gang
    @TimB,我想如果由我来决定,这应该是最好的答案。
    Yanone
    Yanone
    发布于 2022-04-12
    0 人赞同

    I use:

    newObject = globals()[className]()
        
    Akash Ranjan
    Akash Ranjan
    发布于 2022-04-12
    0 人赞同

    我更喜欢用字典来存储类到字符串的映射。

    >>> class AB:
    ...   def __init__(self, tt):
    ...     print(tt, "from class AB")
    >>> class BC:
    ...   def __init__(self, tt):
    ...     print(tt, "from class BC")
    >>> x = { "ab": AB, "bc": BC}
    {'ab': <class '__main__.AB'>, 'bc': <class '__main__.BC'>}
    >>> x['ab']('hello')
    hello from class AB