令人费解的作用域行为
Posted
技术标签:
【中文标题】令人费解的作用域行为【英文标题】:Puzzling scope behaviour 【发布时间】:2012-02-22 12:07:26 【问题描述】:我似乎无法理解这里发生了什么:
class testclass:
def __init__(self):
print "new instance"
myList=[]
if __name__ == "__main__":
inst1=testclass()
inst1.myList.append("wrong")
inst2=testclass()
inst2.myList.append("behaviour")
print "I get the",inst2.myList
输出是:
new instance
new instance
I get the ['wrong', 'behaviour']
我原以为 inst1 中的列表对 inst2 中的列表一无所知,但不知何故它看起来像是 myList 的范围超越类的实例化。 我觉得这非常令人不安和令人费解,还是我在这里遗漏了什么?
谢谢!
【问题讨论】:
【参考方案1】:你定义myList
的方式是一个类属性。
您正在寻找的行为是对象属性之一:
class testclass:
def __init__(self):
print "new instance"
self.myList = []
让我们试试吧:
>>> t1 = testclass()
new instance
>>> t2 = testclass()
new instance
>>> t1.myList.append(1)
>>> t2.myList.append(2)
>>> t1.myList
[1]
>>> t2.myList
[2]
如果您对类属性感兴趣,请查看Class documentation。由于 Python 中的类也是对象,就像(几乎)Python 中的所有东西一样,它们可以有自己的属性。
【讨论】:
【参考方案2】:您在类中声明myList
的方式使其成为class 属性。如果您打算拥有一个 instance 属性,请像这样声明它,它将具有预期的行为:
class testclass:
def __init__(self):
print "new instance"
self.myList=[]
【讨论】:
【参考方案3】:是的,因为这就是类属性的用途。如果你想要一个实例变量,你需要在实例本身上声明它——通常在方法中使用self
。
【讨论】:
【参考方案4】:myList
在 class 实例化时初始化,因为它是在类的主体中声明的,而不是在 object 实例化时。
这些属性然后与实例共享,直到在实例上创建同名变量。
因此,在您的情况下,您使用每个对象来访问相同的 myList
对象(并向其附加一个值)。
【讨论】:
【参考方案5】:class testclass:
def __init__(self):
self.myList=[]
print "new instance"
【讨论】:
【参考方案6】:如果你想让 myList 成为一个实例变量,你应该在 init 函数中定义 self.myList。然后你应该得到你期望的行为。正如你现在所拥有的,我认为 myList 是一个类变量,将由该类的所有实例共享。
【讨论】:
它只会在对象分配之前共享。 不确定我是否理解您的评论。类变量不是总是在所有实例之间共享吗?如果您将 myList 定义为类变量和实例变量,它们仍然是不同的,并且对一个变量的赋值不会影响另一个变量。我错过了什么吗? 这是我的观点。如果你给实例上的变量赋值,你就不能再使用那个实例来访问类变量(除非,也许你删除了实例变量)。 是的,但您始终可以使用类名获取类变量。它还在那里。它仍然是共享的。 我不确定您认为它在何种意义上与无法访问它的对象共享。以上是关于令人费解的作用域行为的主要内容,如果未能解决你的问题,请参考以下文章