Python非直观成员变量behaviou

2024-04-16 12:21:18 发布

您现在位置:Python中文网/ 问答频道 /正文

此脚本:

class testa():
    a = []

class testb():
    def __init__(self):
        self.a = []

ta1 = testa(); ta1.a.append(1); ta2 = testa(); ta2.a.append(2)
tb1 = testb(); tb1.a.append(1); tb2 = testb(); tb2.a.append(2)

print ta1.a, ta2.a, tb1.a, tb2.a

产生以下输出:

^{pr2}$

但我预料到了

[1] [2] [1] [2]

为什么我错了?testa和testb的定义似乎和我一样,那么为什么行为会发生如此剧烈的变化呢?!在

编辑:这似乎不直观,因为它与int和str等其他类型的行为方式不同。由于某些原因,当在init中未初始化时,列表被创建为类变量,但是不管发生什么,int和str都被创建为对象变量。在


Tags: self脚本initdefclassintprintappend
3条回答
<> P>有助于记住Python中的^ {CD1>}语句比任何其他块语句都要接近C++语言的情况。在

在Python中,class语句包含一组要执行的语句,就像defif、或{}。区别在于解释器如何处理块。在流控制块语句的情况下,如ifwhile,解释器按照流控制语句的含义执行块。在def中,解释器保存块并在调用函数对象时执行它。在

class块的情况下,Python立即在一个新的作用域中执行该块,然后在执行完成后使用该作用域中剩余的内容作为类的内容。在

为此:

class testa():
    a = []

Python执行块a = []。最后,范围包含绑定到空列表对象的a。所以这就是你的课程。不是类的任何特定实例,而是类本身。在

它从object继承了一个什么都不做的构造函数,这样当您用ta1 = testa()实例化该类时,会得到一个空实例。然后当您请求ta1.a时,Python找不到名为a的实例变量(因为ta1根本没有实例变量),因此它在类testa中查找a。当然,它会找到;但是对于testa的每个实例,它都会找到相同的一个,因此您得到了所观察到的行为。在

另一方面:

^{pr2}$

完全不同。在这里,一旦类块被执行,类作用域的内容又是一个单一的名称,但这次它是__init__绑定到函数的。这就成了课程的内容。在

现在,当您用testb()实例化这个类时,Python会在类中找到__init__,并用新实例调用该函数。执行该函数将在新实例中创建一个a实例变量。因此,testb()的每个实例都有自己的变量,您可以观察到它的行为。在

带回家消息:Python中的一个^ {CD1>}块是“强>不<强”。只是一组声明的事物,包含在该类的实例中,不像传统的OO-ISH语言,如C++和java。实际执行的代码定义类的内容。这非常方便:您可以在类主体中使用if语句、函数执行的结果以及任何其他上下文中使用的内容来决定在类中定义什么。在

注意:我之前为了简单起见撒了谎。即使是testa的实例也会有一些实例变量,因为默认情况下会为所有实例自动创建一些实例变量,但是在日常的Python中看不到这些变量)。在

testa中,变量a是一个类变量,在所有实例之间共享。^参考相同的列表。在

testb中,变量a是一个对象变量。每个实例都有自己的值。在

有关详细信息,请参见Class and Object Variables。在

一个是类变量,另一个是实例变量。
类变量在类的所有成员之间共享,实例变量对每个实例都是唯一的。
http://docs.python.org/tutorial/classes.html

相关问题 更多 >