Python 列表的就地修改
In-place modification of Python lists
我正在尝试在主列表级别对列表列表执行就地修改。但是,当我尝试修改迭代变量(下例中的row
)时,它似乎创建了一个指向它的新指针而不是修改它。
我的问题的最小例子。
c = [1,2,3]
for x in c:
x = x + 3
print(c) #returns [1,2,3], expected [4,5,6]
上面的例子是我的问题的一个简单例子。有没有办法按元素就地修改 x
并将更改显示在 C 中?
我的问题的不那么简单的例子。我正在将所有 0 切换为 1,反之亦然。
A = [[1,1,0],
[1,0,1],
[0,0,0]]
for row in A:
row = list(map(lambda val: 1 - val, row))
print(A)
预计
A = [[0,0,1],
[0,1,0],
[1,1,1]]
返回
A = [[1,1,0],
[1,0,1],
[0,0,0]]
更新:
到目前为止很好的答案。我感兴趣的是迭代变量(第二个示例中的row
)如何链接到可迭代变量(第二个示例中的A
)。
如果我执行以下操作,反转 A 的每个子列表,它会完美地工作。
为什么下面的例子,我修改了迭代变量,但上面的例子却不行?
A = [[1,1,0],
[1,0,1],
[0,0,0]]
for row in A:
row.reverse()
print(A)
#returns, as expected
A = [[0, 1, 1],
[1, 0, 1],
[0, 0, 0]]
我在文档中找到了这个:https://docs.python.org/3/tutorial/controlflow.html#for
Python’s for statement iterates over the items of any sequence (a list
or a string), in the order that they appear in the sequence.
If you need to modify the sequence you are iterating over while inside
the loop (for example to duplicate selected items), it is recommended
that you first make a copy. Iterating over a sequence does not
implicitly make a copy.
我的第一反应是错误的,当遍历列表时,它 returns 是该列表中的实际项目。但是,似乎无法在迭代时直接编辑它们。这就是为什么遍历整数列表长度有效的原因。
至于为什么.reverse()
函数起作用,我认为是因为它影响的是一个列表而不是一个值。我尝试在非列表数据类型上使用类似的内置函数,例如在字符串上使用 .replace()
,但没有效果。
我试过的所有其他列表函数都有效:.append()
、.remove()
和 .reverse()
,正如您所展示的。我不确定这是为什么,但我希望它能更清楚地说明您可以在 for 循环中做什么。
下面旧问题的答案:
您使用 for 循环的方式不会影响实际列表,只会影响遍历列表的临时变量。有几种方法可以解决此问题。您可以计算到列表的长度并直接修改列表,而不是遍历每个元素。
c = [1,2,3]
for n in range(len(c)):
c[n] += 3
print(c)
您还可以使用 enumerate()
函数循环访问计数器和列表项。
c = [1,2,3]
for n, x in enumerate(c):
c[n] = x + 3
print(c)
在这种情况下,n 是一个计数器,x 是列表中的项目。
最后,您可以使用列表理解生成一个新列表,其中一行包含所需的差异。
c = [1, 2, 3]
d = [x + 3 for x in c]
print(d)
将值插入 Python 中现有列表的常用方法是使用 enumerate
,它可以让您同时遍历索引和值——然后使用索引来操作名单:
c = [1,2,3]
for index, value in enumerate(c):
c[index] = value + 3
对于你的第二个例子,你会做几乎相同的事情:
A = [[1,1,0],
[1,0,1],
[0,0,0]]
for row in A:
for index, val in row:
row[index] = 0 if val > 0 else 1
在第二个示例中,A
中的列表对象成为循环变量 row
—— 因为您只是改变它们(而不是分配给它们),所以您不需要 enumerate
和索引
如果你想在不创建额外变量的情况下保持简洁,你也可以这样做:
c = [1,2,3]
print(id(c))
c[:] = [i+3 for i in c]
print(c, id(c))
输出:
2881750110600
2881750110600 [4, 5, 6]
我正在尝试在主列表级别对列表列表执行就地修改。但是,当我尝试修改迭代变量(下例中的row
)时,它似乎创建了一个指向它的新指针而不是修改它。
我的问题的最小例子。
c = [1,2,3]
for x in c:
x = x + 3
print(c) #returns [1,2,3], expected [4,5,6]
上面的例子是我的问题的一个简单例子。有没有办法按元素就地修改 x
并将更改显示在 C 中?
我的问题的不那么简单的例子。我正在将所有 0 切换为 1,反之亦然。
A = [[1,1,0],
[1,0,1],
[0,0,0]]
for row in A:
row = list(map(lambda val: 1 - val, row))
print(A)
预计
A = [[0,0,1],
[0,1,0],
[1,1,1]]
返回
A = [[1,1,0],
[1,0,1],
[0,0,0]]
更新:
到目前为止很好的答案。我感兴趣的是迭代变量(第二个示例中的row
)如何链接到可迭代变量(第二个示例中的A
)。
如果我执行以下操作,反转 A 的每个子列表,它会完美地工作。
为什么下面的例子,我修改了迭代变量,但上面的例子却不行?
A = [[1,1,0],
[1,0,1],
[0,0,0]]
for row in A:
row.reverse()
print(A)
#returns, as expected
A = [[0, 1, 1],
[1, 0, 1],
[0, 0, 0]]
我在文档中找到了这个:https://docs.python.org/3/tutorial/controlflow.html#for
Python’s for statement iterates over the items of any sequence (a list or a string), in the order that they appear in the sequence.
If you need to modify the sequence you are iterating over while inside the loop (for example to duplicate selected items), it is recommended that you first make a copy. Iterating over a sequence does not implicitly make a copy.
我的第一反应是错误的,当遍历列表时,它 returns 是该列表中的实际项目。但是,似乎无法在迭代时直接编辑它们。这就是为什么遍历整数列表长度有效的原因。
至于为什么.reverse()
函数起作用,我认为是因为它影响的是一个列表而不是一个值。我尝试在非列表数据类型上使用类似的内置函数,例如在字符串上使用 .replace()
,但没有效果。
我试过的所有其他列表函数都有效:.append()
、.remove()
和 .reverse()
,正如您所展示的。我不确定这是为什么,但我希望它能更清楚地说明您可以在 for 循环中做什么。
下面旧问题的答案:
您使用 for 循环的方式不会影响实际列表,只会影响遍历列表的临时变量。有几种方法可以解决此问题。您可以计算到列表的长度并直接修改列表,而不是遍历每个元素。
c = [1,2,3]
for n in range(len(c)):
c[n] += 3
print(c)
您还可以使用 enumerate()
函数循环访问计数器和列表项。
c = [1,2,3]
for n, x in enumerate(c):
c[n] = x + 3
print(c)
在这种情况下,n 是一个计数器,x 是列表中的项目。
最后,您可以使用列表理解生成一个新列表,其中一行包含所需的差异。
c = [1, 2, 3]
d = [x + 3 for x in c]
print(d)
将值插入 Python 中现有列表的常用方法是使用 enumerate
,它可以让您同时遍历索引和值——然后使用索引来操作名单:
c = [1,2,3]
for index, value in enumerate(c):
c[index] = value + 3
对于你的第二个例子,你会做几乎相同的事情:
A = [[1,1,0],
[1,0,1],
[0,0,0]]
for row in A:
for index, val in row:
row[index] = 0 if val > 0 else 1
在第二个示例中,A
中的列表对象成为循环变量 row
—— 因为您只是改变它们(而不是分配给它们),所以您不需要 enumerate
和索引
如果你想在不创建额外变量的情况下保持简洁,你也可以这样做:
c = [1,2,3]
print(id(c))
c[:] = [i+3 for i in c]
print(c, id(c))
输出:
2881750110600
2881750110600 [4, 5, 6]