【问题标题】:When does slicing operator create a shallow copy in Python?切片运算符何时在 Python 中创建浅拷贝?
【发布时间】:2016-05-28 04:58:08
【问题描述】:

我想就 Python 中切片运算符的行为向您寻求帮助。

  1. 一方面我们知道 L[:] 创建列表L 的浅表副本。要验证它,可以打印 id(L), id(L[:]) 并注意到它们是不同的。
  2. 另一方面,我们知道 del L[:] 从原始对象中删除引用。它使原始列表为空 - 而不是它的浅表副本。当然,我同意创建一个浅表副本,然后从中删除引用是没有意义的,所以我理解这里我们想要对原始列表进行操作。

是否有任何规则说明切片运算符何时创建浅拷贝,何时不创建?不手动测试怎么知道?

我搜索了这个并找到了这些主题:

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

【问题讨论】:

  • "是否有规则说明切片运算符何时创建浅拷贝,何时不创建?"是的。它总是创建一个浅拷贝。
  • del L[:] 的行为独立于L[:] 的行为,因为前者转换为list.__delitem__(slice),而后者转换为list.__getitem__(slice)。您可以通过使用__getitem____delitem__ 创建一个类,然后获取和删除一个切片来验证这一点。
  • 在 Python 中,L[:] 调用 L.__getitem__,而 del L[:] 调用 L.__delitem__。换句话说,del 完全改变了语句的含义。
  • 首先感谢文森特编辑我的帖子。发送后我立即对其进行了编辑并试图使其更好,但是您太快了,我没有及时完成。

标签: python


【解决方案1】:

del L[:] 是与访问L[:] 不同的操作,这又是与L[:] = x 不同的操作。

  • del L[:] 使用 slice 对象在对象上调用 __delitem__
  • L[:] 使用 slice 对象调用 __getitem__
  • L[:] = x 使用 slice 对象和 x 调用 __setitem__

这三个操作可以以非常不同的方式实现,具体取决于对象是什么。对于内置列表类型,__delitem__ 删除切片中指定的项目,__setitem__ 将项目替换为给定的项目,__getitem__ 返回一个 new(复制的)列表,其中包含指定的元素。

但是,并非所有对象都必须以这种方式运行。例如,对于 NumPy array,带有切片的 __getitem__ 返回数组的 视图 而不是副本 - 修改视图会改变原始数组。

【讨论】:

  • 感谢 nneonneo 的帮助。您的回答完全与我需要知道的内容有关,以了解在这种情况下发生了什么。
猜你喜欢
  • 1970-01-01
  • 2022-08-10
  • 1970-01-01
  • 2012-02-28
  • 2015-01-13
  • 2011-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多