【发布时间】:2011-10-17 15:36:46
【问题描述】:
正如我在评论 this answer 后才注意到的,Python 3 中的切片返回它们正在切片的任何内容的浅表副本,而不是视图。为什么还是这样?甚至撇开 numpy 使用视图而不是副本进行切片,dict.keys、dict.values 和 dict.items 在 Python 3 中都返回视图这一事实,以及 Python 3 的许多其他方面旨在更多地使用迭代器,使得切片看起来会变得相似。 itertools 确实有一个 islice 函数可以进行迭代切片,但这比普通切片更受限制,并且不提供类似于 dict.keys 或 dict.values 的视图功能。
同样,您可以使用对切片的赋值来修改原始列表,但切片本身是副本而不是视图,这是该语言的一个矛盾方面,并且似乎违反了 @987654322 中说明的几个原则@。
也就是说,你可以做到的事实
>>> a = [1, 2, 3, 4, 5]
>>> a[::2] = [0, 0, 0]
>>> a
[0, 2, 0, 4, 0]
但不是
>>> a = [1, 2, 3, 4, 5]
>>> a[::2][0] = 0
>>> a
[0, 2, 3, 4, 5]
或类似的东西
>>> a = [1, 2, 3, 4, 5]
>>> b = a[::2]
>>> b
view(a[::2] -> [1, 3, 5]) # numpy doesn't explicitly state that its slices are views, but it would probably be a good idea to do it in some way for regular Python
>>> b[0] = 0
>>> b
view(a[::2] -> [0, 3, 5])
>>> a
[0, 2, 3, 4, 5]
似乎有些武断/不受欢迎。
我知道http://www.python.org/dev/peps/pep-3099/ 以及它说“切片和扩展切片不会消失(即使__getslice__ 和__setslice__ API 可能被替换)的部分,它们也不会返回视图标准对象类型。”,但链接的讨论没有提及为什么做出关于使用视图进行切片的决定;事实上,在原帖中列出的建议中,大多数关于该具体建议的 cmets 似乎都是积极的。
是什么阻止了这样的事情在 Python 3.0 中实现,Python 3.0 专门设计为不严格向后兼容 Python 2.x,因此是实现这种设计更改的最佳时机,是否存在在未来的 Python 版本中有什么可能阻止它吗?
【问题讨论】:
-
我怀疑答案可能是由于涉及 Python 列表的低级实现(针对速度进行了优化)的技术原因,视图无法正常工作。我将尝试查看源代码以支持这一点。
-
但是,我们需要 my_list[:] 的替代方案,执行“from copy import shallowcopy”会很糟糕。
-
@utdemir 另一种选择是
list(my_list)。它没有那么漂亮,但仍然相当简洁。 -
@Wallacoloo:它还允许混合列表和迭代器/生成器/等。 (另一方面,它将任何元组转换为列表,如果您想保持不变性,这可能是不可取的。)
-
实际上,我怀疑这也会导致在移植到 Python 3 时出现很多细微的错误,即使 2to3 确实处理了它。
标签: python python-3.x language-design slice