双循环给出意想不到的答案



我已经在Python和JS上测试了这个例子,由于结果相同,因此仅提供前者。考虑代码段

a = []
b = []
for i in range(3):
for j in range(2):
a.append(0)
print("a = ",a)
b.append(a)
print("b = ",b)

a用作列表时,结果为[[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0]]。如果a是字符串,

a = ""
b = []
for i in range(3):
for j in range(2):
a+= "0"
print("a = ",a)
b.append(a)
print("b = ",b)

这给了['00','0000','000000'].

使用列表编写代码时,我期待输出[[0,0],[0,0,0,0],[0,0,0,0,0,0],类似于字符串,但呈列表形状。我一直试图解决这个问题,但无济于事。我错过了什么?

您正在添加对列表的引用,而不是实际列表。改用

b.append(a[:])

a是一个列表时,调用b.append(a)会将对a的引用附加到b的末尾。然后,下次运行 for 循环时,a会发生变化,因此b中对a的所有引用也会更改。

与列表不同,字符串是不可变的,因此b.append(a)a的副本附加到b的末尾。您可以将代码更改为b.append(a[:])以获取使用字符串查找的行为,这会在追加之前创建a的副本。

问题是 a 是对每个循环中使用的相同数组的引用。您已将 a 附加到 b,但随后在下一次迭代中引用相同的数组。

b.append(list(a))

这会创建您尝试追加的数组的副本。

你缺少什么 ->追加如何工作以及你正在追加什么。

您正在为每次迭代添加对b即 B 外观的引用

b = [reference_to_a, reference_to_a, referemce_to_a]

最后,对 A 的引用是最新的,即上次迭代的引用。

即无论上次迭代的值是什么,它都将与所有值相同。

您可以在所有情况下通过检查对象的id来验证这一点。

如何解决这个问题 ->使用adeepcopy并附加它或创建一个新的a元素列表。

您可以验证上述声明

>>> a = [1]
>>> b = [1]
>>> 
>>> a.append(b)
>>> a.append(b)
>>> a.append(b)
>>> a.append(b)
>>> 
>>> a
[1, [1], [1], [1], [1]]
>>> 
>>> 
>>> b.append(2)
>>> a
[1, [1, 2], [1, 2], [1, 2], [1, 2]]

所以要解决这个用途

a.append(deepcopy(b))

您可以验证这一点

>>> 
>>> a =[1]
>>> b = [1]
>>> 
>>> from copy import deepcopy
>>> 
>>> a.append(deepcopy(b))
>>> a
[1, [1]]
>>> b
[1]
>>> b.append(3)
>>> a
[1, [1]]
>>> b
[1, 3]
>>> a.append(deepcopy(b))
>>> a
[1, [1], [1, 3]]
>>> b.append(5)
>>> a
[1, [1], [1, 3]]
>>> a.append(deepcopy(b))
>>> a
[1, [1], [1, 3], [1, 3, 5]]

最新更新