因此,在测试一些代码时,我发现Python中有一些奇怪的功能,即两个不同值的变量评估为相等。产生上述行为的代码如下
class Foo:
def __init__(self):
self.x = [1,2,3]
self.y = self.x
def ChangeX(self):
self.x.append(4)
def equals(self):
print(self.x==self.y)
当我运行此代码时,变量会按原样初始化。如果我跑
f = Foo()
f.equals()
输出为True,我可以理解,因为此时f.x和f.y都保持相同的值。但是,当我跑
时r = Foo()
r.ChangeX()
r.equals()
输出仍然是真的。这让我很困惑。 r.x和r.y显然不再保持相同的值(按顺序打印它们甚至提供不同的输出),但Python似乎相信这两个变量彼此相等。
我有一种预感,这与我正在使用课程这一事实有关;但我仍然不知道这里究竟发生了什么,或者如何“修复”它。谁能解释一下?
答案 0 :(得分:3)
self.x
和self.y
都在内存中引用相同的列表对象。这意味着,当您更新一个时,另一个将反映更改。
您可以在以下演示中看到此行为:
>>> a = [1, 2, 3]
>>> b = a
>>>
>>> # The contents of a and b are the same
>>> a
[1, 2, 3]
>>> b
[1, 2, 3]
>>>
>>> # And their ids are the same
>>> id(a)
33908856
>>> id(b)
33908856
>>>
>>> a.append(4)
>>> a
[1, 2, 3, 4]
>>> b
[1, 2, 3, 4]
>>>
如果您想更改此行为,可以将self.y
分配给self.x
的浅表副本:
self.y = self.x[:]
参见下面的演示:
>>> a = [1,2,3]
>>> b = a[:]
>>>
>>> # The contents of a and b are the same
>>> a
[1, 2, 3]
>>> b
[1, 2, 3]
>>>
>>> # But their ids are different
>>> id(a)
33984680
>>> id(b)
33984960
>>>
>>> a.append(4)
>>> a
[1, 2, 3, 4]
>>> b
[1, 2, 3]
>>>
答案 1 :(得分:2)
您没有两个列表。您有一个列表x
以及一个名为list x
的列表y
的引用。修改列表x时,也会修改引用y后面的值。详细了解此here。
答案 2 :(得分:1)
self.x
和self.y
引用相同的数据。当你这样做
self.y = self.x
将两个变量绑定到内存中的同一个数组。
如果您希望它们与众不同,最好这样做
self.y = list(self.x)
答案 3 :(得分:0)
正如您所看到的,self.y = self.x
只是将y
分配给x
:
class Foo:
def __init__(self):
self.x = [1,2,3]
self.y = self.x
def ChangeX(self):
self.x.append(4)
def equals(self):
print(self.x==self.y)
f = Foo()
f.equals()
f.ChangeX()
f.equals()
print(f.x)
print(f.y)
#True
#True
#[1, 2, 3, 4]
#[1, 2, 3, 4]