【问题标题】:Using Variables for Class Names in Python?在 Python 中使用变量作为类名?
【发布时间】:2010-09-18 10:09:19
【问题描述】:

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

$className = "MyClass";

$newObject = new $className();

你是如何在 Python 中做这种事情的?或者,我是否完全不了解与 Python 的一些根本区别,如果是,那是什么?

【问题讨论】:

  • 我很想知道你为什么需要这样做——我认为可能有一种更 Pythonic 的方式,它不需要变量类名。
  • “我完全没有意识到与 Python 的一些根本区别吗?如果是,那是什么?”可能。你为什么使用上面例子中的代码?请提供一个更大的示例来提供一些上下文。
  • 很有趣,但我同意 TimB,我想听听这个用例。
  • python中没有变量,只有名字。
  • 在最近的一个案例中,我实现了一个类的两个不同的子类。对于相同的一般工作,它们具有相似的不同实现,并且具有大致相同的 API。我猜这是一种策略模式?无论如何,我想根据上下文动态使用其中一个。

标签: python dynamic-typing


【解决方案1】:

假设 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 小时一直在窃听。谢谢。
【解决方案2】:

在 Python 中,

className = MyClass
newObject = className()

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

作为一个具体的例子:

>>> className = list
>>> newObject = className()
>>> newObject
[]

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

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

【讨论】:

  • downvoted,因为您的解决方案与问题中的解决方案不匹配。他正在寻找的是一个带有字符串的类的实例化。
  • 请遵守 PEP8。使用混合大小写名称有点违背 SO 所代表的价值观。
  • 同意第一条评论,这对于存储在变量中的类名不起作用
  • 它适用于 OP,这就是他接受@Matt 这个答案的原因。它也适用于我。
  • @reggie,以为他问了一个字符串,我想提出问题的人也可以用 Greg Hewgill 解决方案解决问题。因为,我们要使用的所有类必须已经存在,他可以将它们导入到一个名称中使用,而不是随机字符串!
【解决方案3】:

如果您需要在 Python 中创建一个动态类(即名称为变量的类),您可以使用 type() ,它需要 3 个参数: 名称、基数、属性

>>> class_name = 'MyClass'
>>> klass = type(class_name, (object,), {'msg': 'foobarbaz'})

<class '__main__.MyClass'>

>>> inst = klass()
>>> inst.msg
foobarbaz
  • 但是请注意,这不会“实例化”对象(即不调用构造函数等。它会创建一个具有相同名称的 new(!) 类。

【讨论】:

    【解决方案4】:

    如果你有这个:

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

    那么你通常会这样做:

    >>> x = MyClass()
    MyClass
    

    但你也可以这样做,这就是我认为你要问的:

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

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

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

    【讨论】:

    • 天啊,不! eval 函数是邪恶的。不要使用它。
    • @TimB,如果由我决定,我认为这应该是最好的答案。
    【解决方案5】:

    我用:

    newObject = globals()[className]()
    

    【讨论】:

      猜你喜欢
      • 2015-08-03
      • 2017-09-01
      • 1970-01-01
      • 2018-10-30
      • 1970-01-01
      • 2016-04-20
      • 2021-06-25
      • 2017-01-07
      • 1970-01-01
      相关资源
      最近更新 更多