Python 在迭代中就地/直接更新列表-这是否有效?

Python 在迭代中就地/直接更新列表-这是否有效?,python,nested-lists,updating,Python,Nested Lists,Updating,我无意中注意到直接更新列表中的元素是有效的 有很多关于更新列表的问答。然而,我检查过的所有答案都表明 在迭代过程中,python生成列表元素的副本 更改复制的元素不会更改列表本身 您需要使用列表理解、列表索引或类似的方法来更改列表 但在下面的示例中,我可以直接更新列表 我找到的关于这个主题的所有答案都相当陈旧,那么这是后来添加到python中的吗 # COMPREHENSION ================================== li = [ ["spam

我无意中注意到直接更新列表中的元素是有效的

有很多关于更新列表的问答。然而,我检查过的所有答案都表明

  • 在迭代过程中,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, "      <<<<<<<<<<<<<")
理解================================== 李=[ [“spam1”、“eggs1”], [“spam2”、“eggs2”] ] 打印(“\n理解--------------------”) 打印(“输入”,li) li=[[“新”,l[1]]表示li中的l] 打印(“输出”,li) #索引=========================================== 李=[ [“spam1”、“eggs1”], [“spam2”、“eggs2”] ] 打印(“\n索引--------------------”) 打印(“输入”,li) 对于索引,枚举中的l(li): li[index]=[“新”,l[1]] 打印(“输出”,li) #到位======================================== 李=[ [“spam1”、“eggs1”], [“spam2”、“eggs2”] ] 打印(“\n在-----------------”)
print(“INPUT”,li,”这是有效的,因为您使用列表中的元素的索引替换了该元素,这对迭代没有影响


禁止向正在迭代的列表中添加或删除元素,这是您从未执行过的操作。

所有操作实际上都按预期进行。 您是对的,内部迭代元素只是复制的,所以更改复制的元素不会更改实际列表。请参见示例:

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
指向内部列表本身,而不是其副本。您可以实际修改此内部列表元素。如下所示:

In [8]: for a in z:
  ...:     if a[0] ==3:
  ...:         a[0] = 7

In [9]: z
Out[9]: [[1, 2], [7, 4], [5, 6]]
甚至从中添加/删除元素:

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]]

在第三个示例中,我使用的唯一索引是内部列表元素。这就是你的意思吗?在阅读Serge的答案后,我已经预料到了类似的情况。谢谢你的清晰解释。
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]]