我需要用 Python 创建一个列表,所以我输入了以下内容:
myList = [[1] * 4] * 3
这个列表看起来像这样:
[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
然后我改变了最里面的一个值:
myList[0][0] = 5
现在我的列表是这样的:
[[5, 1, 1, 1], [5, 1, 1, 1], [5, 1, 1, 1]]
这不是我想要的。 有没有人能解释一下发生了什么,以及如何避开这个问题?
当你写[ x ] * 3时,实际上你得到了列表[ x,x,x ]。 也就是说,一个包含3个相同 x 的引用的列表。 当你修改这个单个的 x 时,它可以通过对它的所有三个引用被看到。
要修复它,您需要确保在每个位置创建一个新列表。 一种方法是
[[1]*4 for _ in range(3)]
这将重新评估[1] * 4每次,而不是评估一次,使3引用列表1。
你可能想知道为什么。 * 不能像列表内涵那样制造独立的物体。 这是因为乘法运算符 * 操作对象,看不到表达式。 当您使用 * 将[[1] * 4]乘以3时,* 只看到1元素列表[[1] * 4]的计算结果为,而不是[1] * 4表达式文本。 * 不知道如何复制该元素,不知道如何重新评估[1] * 4] ,甚至不知道您需要复制,一般来说,甚至可能没有复制该元素的方法。
唯一的选项 * 是对现有的子列表进行新的引用,而不是尝试建立新的子列表。 其他任何东西都是不一致的,或者需要重新设计。
相比之下,列表内涵在每次迭代时重新评估元素表达式。 [1] * 4对于范围(3)中的 n ]每次重新计算[1] * 4,原因相同[ x * * 2对于范围(3)中的 x ]每次重新计算 x * * 2。 对[1] * 4的每一次评估都会产生一个新的列表,所以列表内涵表可以做你想做的事情。
顺便说一句,[1] * 4也不复制[1]的元素,但这无关紧要,因为整数是不可变的。 1.value = 2是不可能的哈
size = 3
matrix_surprise = [[0] * size] * size
matrix = [[0]*size for i in range(size)]
实时 Python 可视化
我来解答!分析一下:
你的代码
lst = [[1] * 4] * 3
这相当于:
lst1 = [1]*4
lst = [lst1]*3
这意味着 lst 是一个有3个元素都指向 lst1的列表。 这意味着下面两行是等价的:
lst[0][0] = 5
lst1[0] = 5
因为 lst [0]只不过是 lst1。
你可以使用列表内涵:
lst = [ [1]*4 for n in xrange(3) ]
在这种情况下,对每个 n 重新计算表达式,出现不同的列表。
[[1] * 4] * 3
甚至
[[1, 1, 1, 1]] * 3
创建一个引用内部[1,1,1,1]3次的列表——而不是内部列表的三个副本,因此任何时候(在任何位置)修改列表,都会看到三次更改。
和这个例子一样:
inner = [1,1,1,1]>>> outer = [inner]*3>>> outer[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]>>> inner[0] = 5>>> outer[[5, 1, 1, 1], [5, 1, 1, 1], [5, 1, 1, 1]]
这样就不合情合理了。