Python中切片运算符何时创建浅拷贝?

6
我想请你帮忙解决一个有关 Python 切片操作符行为的问题。
  1. 一方面,我们知道 L[:] 会创建列表 L 的一个浅拷贝。可以通过打印 id(L), id(L[:]) 并观察它们是否不同来验证。
  2. 另一方面,我们知道 del L[:] 会从原始对象中删除引用。这会导致原始列表为空 - 而不是其浅拷贝。当然,我同意先创建一个浅拷贝,然后再从中删除引用可能没有什么意义,所以我理解这里我们要操作的是原始列表。

是否有规定说明切片操作符何时创建浅拷贝,何时不创建呢?我如何在不进行手动测试的情况下知道呢?

我搜索了一下,并找到了以下主题:

但不幸的是,它们并没有回答我的问题,至少我没有看到。


“有没有规定说明切片操作符何时创建浅拷贝,何时不创建?” 是的。它总是创建浅拷贝。 - kindall
3
del L[:] 的行为与 L[:] 的行为无关,因为前者被翻译成 list.__delitem__(slice) 而后者是 list.__getitem__(slice)。你可以创建一个有 __getitem____delitem__ 方法的类,并获取和删除一个切片来验证这一点。 - Sergei Lebedev
2
在Python中,L[:] 调用的是 L.__getitem__,而 del L[:] 则会调用 L.__delitem__。换句话说,del 完全改变了语句的含义。 - GingerPlusPlus
首先感谢Vincent编辑我的帖子。我刚发完就编辑了一下,想要改进,但是你太快了,我来不及。 - Drizzt
1个回答

7

del L[:] 是一种独立的操作,与访问 L[:] 不同,而访问 L[:] = x 又是另一种不同的操作。

  • del L[:] 在对象上使用一个 slice 对象调用了 __delitem__ 方法。
  • L[:] 使用该 slice 对象调用了 __getitem__ 方法。
  • L[:] = x 使用该 slice 对象和 x 调用了 __setitem__ 方法。

这三个操作可以根据对象的不同实现得非常不同。对于内置的列表类型,__delitem__ 擦除了在切片中指定的项,__setitem__ 用给定的项替换这些项,并且 __getitem__ 返回由指定元素组成的一个新(复制的)列表。

然而,并非所有对象都必须像这样表现。例如,对于NumPy array,使用切片调用 __getitem__ 返回数组的一个 视图,而不是一个副本 - 修改视图会改变原始数组。


感谢nneonneo的帮助。你的答案正好涉及到我需要了解的内容,让我明白了这种情况下正在发生什么。 - Drizzt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接