嵌套列表索引[重复]

2024-01-02

我在下面显示的代码中使用 Python 中的嵌套列表时遇到了一些问题。

基本上,我有一个包含所有 0 值的 2D 列表,我想在循环中更新列表值。

然而,Python 并没有产生我想要的结果。有什么我误解的吗range()和Python列表索引?

some_list = 4 * [(4 * [0])]
for i in range(3):
    for j in range(3):
        some_list[i+1][j+1] = 1
for i in range(4):
    print(some_list[i])

我期望的结果是:

[0, 0, 0, 0]
[0, 1, 1, 1]
[0, 1, 1, 1]
[0, 1, 1, 1]

但Python的实际结果是:

[0, 1, 1, 1]
[0, 1, 1, 1]
[0, 1, 1, 1]
[0, 1, 1, 1]

这里发生了什么?


该问题是由 python 选择通过引用传递列表这一事实引起的。

通常变量是“按值”传递的,因此它们独立运行:

>>> a = 1
>>> b = a
>>> a = 2
>>> print b
1

但由于列表可能变得相当大,Python 选择只使用引用(C 术语中的“指针”),而不是在内存中移动整个列表。如果将一个变量分配给另一个变量,则只需分配对其的引用。这意味着您可以有两个变量指向内存中的同一列表:

>>> a = [1]
>>> b = a
>>> a[0] = 2
>>> print b
[2]

所以,在你的第一行代码中你有4 * [0]. Now [0]是一个指向内存中值 0 的指针,当你乘以它时,你会得到四个指向内存中同一位置的指针。但是当你改变其中一个值时,Python 就知道指针需要改变以指向新值:

>>> a = 4 * [0]
>>> a
[0, 0, 0, 0]
>>> [id(v) for v in a]
[33302480, 33302480, 33302480, 33302480]
>>> a[0] = 1
>>> a
[1, 0, 0, 0]

当你乘以这个列表时,问题就出现了——你得到了列表指针的四个副本。现在,当您更改一个列表中的某个值时,所有四个值都会一起更改:

>>> a[0][0] = 1
>>> a
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]

解决方案是避免第二次乘法。循环完成这项工作:

>>> some_list = [(4 * [0]) for _ in range(4)]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌套列表索引[重复] 的相关文章

随机推荐