如果Python切片复制引用,为什么我不能用它来修改原始列表?

Hei*_*erg 6 python reference list

我知道切片列表不会生成列表中对象的副本;它只是复制对它们的引用。

但如果是这样的话,那为什么这行不通呢?

l = [1, 2, 3]

# Attempting to modify the element at index 1
l[0:2][-1] = 10

# but the attempt fails. The original list is unchanged
l
> [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

不应该l[0:2][-1]指向原始列表索引 1 处的元素吗?

Bre*_*arn 3

您是对的,切片不会复制列表中的项目。但是,它确实创建了一个新的列表对象。

您的评论表明存在误解:

# Attempting to modify the element at index 1
l[0:2][-1] = 10
Run Code Online (Sandbox Code Playgroud)

这不是对元素的修改,而是对列表的修改。换句话说,它实际上是“更改列表,使索引 1 现在指向数字 10”。由于您的切片创建了一个新列表,因此您只需更改该新列表以指向其他某个对象即可。

在您对 oldrinb 的回答的评论中,您说:

为什么l[0:1]l[0:1][0]不同?它们不应该引用同一个对象,即 的第一项吗l

除了它l[0:1]是一个列表而它l[0:1][0]是一个元素之外,这里又存在同样的误解。假设这some_list是一个列表,索引处的对象ixobj。这:

some_list[ix] = blah
Run Code Online (Sandbox Code Playgroud)

。。。是对 的操作some_list。对象obj不涉及。这可能会令人困惑,因为这意味着some_list[ix]根据其位于分配的哪一侧,语义略有不同。如果你这样做

blah = some_list[ix] + 2
Run Code Online (Sandbox Code Playgroud)

。。.那么您确实正在操作列表内的对象(即,它与 相同obj + 2)。但是,当索引操作位于赋值的左侧时,它不再涉及所包含的对象,而只涉及列表本身。

当您分配给列表索引时,您正在修改列表而不是其中的对象。所以在你的例子中l[0]与 相同l[0:2][0],但这并不重要;因为您的索引是一个分配目标,所以它正在修改列表并且不关心其中已经有什么对象。