在 place/directly 更新列表中的迭代列表中 - 这应该有效吗?
In place/directly updating list of lists inside iteration - Should this be working?
我无意中注意到直接更新列表列表中的元素是可行的。
有很多关于更新列表列表的问答。然而我检查的所有答案都表明
- 在迭代中 python 生成列表元素的副本
- 更改复制的元素不会更改列表本身
- 您需要使用列表理解、列表索引或类似的东西来更改列表
但在下面的例子中我可以直接更新一个列表。
我找到的关于该主题的所有答案都相当陈旧,所以稍后是否将其添加到 python?
# COMPREHENSION ==================================
li = [
["spam1", "eggs1"],
["spam2", "eggs2"]
]
print("\nCOMPREHENSION ---------------")
print("INPUT", li)
li = [["new", l[1]] for l in li]
print("OUTPUT", li)
# INDEX ===========================================
li = [
["spam1", "eggs1"],
["spam2", "eggs2"]
]
print("\nINDEX -----------------")
print("INPUT", li)
for index, l in enumerate(li):
li[index] = ["new", l[1]]
print("OUTPUT", li)
# IN PLACE ========================================
li = [
["spam1", "eggs1"],
["spam2", "eggs2"]
]
print("\nIN PLACE --------------")
print("INPUT", li, " <<<<<<<<<<<<<")
for i in li:
i[0] = f'new'
print("OUTPUT", li, " <<<<<<<<<<<<<")
结果
COMPREHENSION ---------------
INPUT [['spam1', 'eggs1'], ['spam2', 'eggs2']]
OUTPUT [['new', 'eggs1'], ['new', 'eggs2']]
INDEX -----------------
INPUT [['spam1', 'eggs1'], ['spam2', 'eggs2']]
OUTPUT [['new', 'eggs1'], ['new', 'eggs2']]
IN PLACE --------------
INPUT [['spam1', 'eggs1'], ['spam2', 'eggs2']] <<<<<<<<<<<<<
OUTPUT [['new', 'eggs1'], ['new', 'eggs2']] <<<<<<<<<<<<<
这是有效的,因为您替换列表中的元素使用其索引,这对迭代没有影响。
禁止向正在迭代的列表中添加或删除元素,这是你永远不会做的。
一切都按预期进行。
你是对的,内部迭代元素只是被复制,所以改变复制的元素不会改变实际的列表。参见示例:
In [1]: x = [1,2,3,4,5,6,7,8]
In [2]: for a in x:
...: if a ==2:
...: a=3
In [3]: x
Out[3]: [1, 2, 3, 4, 5, 6, 7, 8]
当列表的一个元素实际上是一个列表时会发生什么?
In [4]: z = [[1,2],[3,4],[5,6]]
In [5]: for a in z:
...: if a[0] ==3:
...: a = [7,8]
In [6]: z
Out[6]: [[1, 2], [3, 4], [5, 6]]
您有一个分配给 a
的内部列表的副本,因此分配给 a
另一个列表不会更改外部列表 z
。
然而在迭代中实际复制的不是内部列表,而是a reference to it。所以 a
指向内部列表本身,而不是它的副本。您实际上可以修改此内部列表元素。喜欢这里:
In [8]: for a in z:
...: if a[0] ==3:
...: a[0] = 7
In [9]: z
Out[9]: [[1, 2], [7, 4], [5, 6]]
甚至 add/remove 个元素:
In [10]: for a in z:
...: if a[0] ==1:
...: a.append(22)
In [10]: z
Out[10]: [[1, 2, 22], [7, 4], [5, 6]]
我无意中注意到直接更新列表列表中的元素是可行的。
有很多关于更新列表列表的问答。然而我检查的所有答案都表明
- 在迭代中 python 生成列表元素的副本
- 更改复制的元素不会更改列表本身
- 您需要使用列表理解、列表索引或类似的东西来更改列表
但在下面的例子中我可以直接更新一个列表。
我找到的关于该主题的所有答案都相当陈旧,所以稍后是否将其添加到 python?
# COMPREHENSION ==================================
li = [
["spam1", "eggs1"],
["spam2", "eggs2"]
]
print("\nCOMPREHENSION ---------------")
print("INPUT", li)
li = [["new", l[1]] for l in li]
print("OUTPUT", li)
# INDEX ===========================================
li = [
["spam1", "eggs1"],
["spam2", "eggs2"]
]
print("\nINDEX -----------------")
print("INPUT", li)
for index, l in enumerate(li):
li[index] = ["new", l[1]]
print("OUTPUT", li)
# IN PLACE ========================================
li = [
["spam1", "eggs1"],
["spam2", "eggs2"]
]
print("\nIN PLACE --------------")
print("INPUT", li, " <<<<<<<<<<<<<")
for i in li:
i[0] = f'new'
print("OUTPUT", li, " <<<<<<<<<<<<<")
结果
COMPREHENSION ---------------
INPUT [['spam1', 'eggs1'], ['spam2', 'eggs2']]
OUTPUT [['new', 'eggs1'], ['new', 'eggs2']]
INDEX -----------------
INPUT [['spam1', 'eggs1'], ['spam2', 'eggs2']]
OUTPUT [['new', 'eggs1'], ['new', 'eggs2']]
IN PLACE --------------
INPUT [['spam1', 'eggs1'], ['spam2', 'eggs2']] <<<<<<<<<<<<<
OUTPUT [['new', 'eggs1'], ['new', 'eggs2']] <<<<<<<<<<<<<
这是有效的,因为您替换列表中的元素使用其索引,这对迭代没有影响。
禁止向正在迭代的列表中添加或删除元素,这是你永远不会做的。
一切都按预期进行。 你是对的,内部迭代元素只是被复制,所以改变复制的元素不会改变实际的列表。参见示例:
In [1]: x = [1,2,3,4,5,6,7,8]
In [2]: for a in x:
...: if a ==2:
...: a=3
In [3]: x
Out[3]: [1, 2, 3, 4, 5, 6, 7, 8]
当列表的一个元素实际上是一个列表时会发生什么?
In [4]: z = [[1,2],[3,4],[5,6]]
In [5]: for a in z:
...: if a[0] ==3:
...: a = [7,8]
In [6]: z
Out[6]: [[1, 2], [3, 4], [5, 6]]
您有一个分配给 a
的内部列表的副本,因此分配给 a
另一个列表不会更改外部列表 z
。
然而在迭代中实际复制的不是内部列表,而是a reference to it。所以 a
指向内部列表本身,而不是它的副本。您实际上可以修改此内部列表元素。喜欢这里:
In [8]: for a in z:
...: if a[0] ==3:
...: a[0] = 7
In [9]: z
Out[9]: [[1, 2], [7, 4], [5, 6]]
甚至 add/remove 个元素:
In [10]: for a in z:
...: if a[0] ==1:
...: a.append(22)
In [10]: z
Out[10]: [[1, 2, 22], [7, 4], [5, 6]]