我是编程新手,所以请不要因为提出愚蠢的问题而杀了我。 我一直在努力理解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()
?
请帮助我,因为如果我编写一些我自己不理解的代码,这有点傻。
答案 0 :(得分:5)
这里会发生以下情况:
class Test(object):
def __init__(self):
print "WORKS!"
room = globals()['Test']
您可以按照自己想要的方式获得Test
room
。验证这一点:
room is Test
应该提供True
。
type(room())
给出:<class '__main__.Test'>
你向后退一步:room()
返回与Test()
相同的内容 - 该类的实例。 type()
“解除”这一步骤。获取对象的类型 - 当然,这是Test
。
type(room)
给出:<type 'type'> # What????
当然 - 它是(新风格)类的类型。与type(Test)
相同。
但请注意,
在我的程序中,我需要根据函数返回的字符串从其他类中调用一个类。我找到了两个解决方案:一个使用
getattr()
,另一个使用globals()
/locals()
。
创建一个明确单独的dict可能会更好。在这里,您可以完全控制在该上下文中允许哪些对象/类/ ...,哪些不是。
答案 1 :(得分:1)
首先,我会选择getattr
。
在您的示例中,room
等于Test
并且是一个类。它的类型是type
。
当您致电room()
时,您实例化Test
,因此room()
会评估Test
的实例,其类型为Test
。
答案 2 :(得分:1)
在Python中,类也是对象。所有这一切都是:
class Test(object):
def __init__(self):
print "WORKS!"
创建一个类对象并将其绑定到名称Test
。就像这样:
x = []
创建一个列表对象并将其绑定到名称x
。
Test()
不是创建实例的神奇语法。 Test
是完全普通的变量查找,而()
完全是普通的“使用空参数调用”。恰好,调用一个类将创建该类的实例。
如果遵循,那么实例化基于将类的名称作为字符串选择的类的问题归结为查找存储在变量中的对象的更简单的问题。在给定字符串x
的情况下,将该列表绑定到名称"x"
的问题与此完全相同。一旦你在任何旧变量中引用了类,你只需调用它来创建你的实例。
globals()
返回一个字典,将全局变量的名称映射到它们的值。因此,globals()['Test']
会为您提供课程Test
,就像globals()['x']
能够获得列表一样容易。然而,使用这样的globals()
通常不被认为是很好的风格;您的模块可能包含大量的callables(包括从其他模块导入的一组),如果可以使函数返回其名称,则不希望被意外调用。鉴于类只是普通对象,您可以将它们放在您自己制作的字典中:
classes = {
'Test': Test,
'SomethingElse': Something,
...
}
这需要更多的输入,但它也更容易看到预期的用途,并且它提供了更多的灵活性,因为您也可以轻松地将此字典传递给其他模块并在其他地方进行实例化(你可以用globals()
做到这一点,但是你变得非常奇怪了。
现在,type(room)
为type
。同样,这只是类本身也是对象的简单结果。如果一个类是一个对象,那么它也应该是某个类的实例。那是什么课? type
,“类型的类型”。就像任何类定义其所有实例的共同行为一样,类type
定义了所有类的共同行为。
只是为了让你的大脑受到伤害,type
是它自己的一个实例(因为type
也是一个类,而type
是类的类)。它是object
的子类(因为所有type
个实例都是object
个实例,但并非所有object
个实例都是type
个实例),还有一个实例object
(因为object
是一切都是实例的根类。)
但是,您通常可以忽略type
作为高级主题。 :)