3

我是编程新手,所以请不要因为问愚蠢的问题而杀了我。我一直在尝试了解 Python 中的所有此类业务,但我已经到了仅通过谷歌就无法找到我的问题的答案的地步。

在我的程序中,我需要根据函数返回的字符串从其他类中调用一个类。我找到了两种解决方案:一种是使用getattr(),另一种是使用globals()/ locals()

决定寻求第二个解决方案并让它工作,但我真的不明白它是如何工作的。

于是就有了代码示例:

class Test(object):
    def __init__(self):
        print "WORKS!"

room = globals()['Test'] 
room()

type(room())给出:

<class '__main__.Test'>

type(room)给出:

<type 'type'> # What????

它看起来像是room()一个类对象,但不应该room代替room()吗?

请帮助我,因为如果我编写一个我自己不理解的代码有点傻。

4

3 回答 3

5

这里发生的情况如下:

class Test(object):
    def __init__(self):
        print "WORKS!"

room = globals()['Test']

在这里你得到Testroom你想要的方式。验证这一点:

room is Test

应该给True

type(room())给出:

<class '__main__.Test'>

您向后退一步:room()返回与将相同的Test()- 该类的实例。type()“撤消”这一步。获取对象的类型 - 这当然是Test.

type(room)给出:

<type 'type'> # What????

当然 - 它是(新样式)类的类型。与 相同type(Test)


但是请注意,对于

在我的程序中,我需要根据函数返回的字符串从其他类中调用一个类。我找到了两种解决方案:一种是使用getattr(),另一种是使用globals()/ locals()

最好创建一个明确单独的字典。在这里,您可以完全控制在该上下文中允许哪些对象/类/...,哪些不允许。

于 2012-10-05T12:05:14.373 回答
1

首先,我会选择getattr

在您的示例中,room等于Test并且是一个类。它的类型是type.

当您调用时room(),您将实例化Test,因此room()计算为 的实例Test,其类型为Test

于 2012-10-05T12:01:07.710 回答
1

在 Python 中,类也是对象。所有这一切:

class Test(object):
    def __init__(self):
        print "WORKS!"

是创建一个类对象并将其绑定到 name Test。就像这样:

x = []

创建一个列表对象并将其绑定到 name x

Test()不是创建实例的神奇语法。这Test是非常普通的变量查找,()也是非常普通的“使用空参数调用”。碰巧调用一个类将创建该类的一个实例。

如果遵循那么您将基于将类名称作为字符串选择的类实例化的问题归结为查找存储在变量中的对象的简单得多的问题。x给定字符串,这与将列表绑定到 name 完全相同的问题"x"。一旦您在任何旧变量中获得了对该类的引用,您就可以简单地调用它来创建您的实例。

globals()返回一个字典,将全局变量的名称映射到它们的值。因此globals()['Test'],您将获得课程Test,就像globals()['x']获得列表一样容易。然而,这样使用通常不被认为是很好的风格globals();如果可以使函数返回它们的名称,您的模块可能包含大量可调用对象(包括从其他模块导入的一堆),您不希望被意外调用。鉴于类只是普通对象,您可以将它们放入自己制作的字典中:

classes = {
    'Test': Test,
    'SomethingElse': Something,
    ...
}

这涉及更多的输入,但也更容易看到预期的用途,并且它为您提供了更多的灵活性,因为您还可以轻松地将此字典传递给其他模块并在其他地方进行实例化(您可以这样做,globals()但是你会变得很奇怪)。

现在,type(room)暂时type。同样,这只是类本身也是对象这一事实的简单结果。如果一个类是一个对象,那么它也应该是某个类的一个实例。那是什么课?type,“类型的类型”。就像任何类定义其所有实例的共同行为一样,该类type定义所有类的共同行为。

而只是为了让你的大脑受伤,type是它自己的一个实例(因为type也是一个类,并且type是类的类)。它是object(因为所有type实例都是object实例,但并非所有object实例都是type实例)的子类,也是object(因为object是所有事物都是实例的根类)的实例。

但是,您通常可以type将其视为高级主题而忽略。:)

于 2012-10-05T14:31:38.813 回答