为什么在Python 3中,切片仍然是副本而不是视图?
为什么在Python 3中,切片仍然是副本而不是视图?
在我评论了这个答案之后,我才注意到在Python 3中,切片返回的是被切片对象的浅拷贝,而不是视图。为什么仍然如此?即使不考虑numpy在切片中使用视图而不是拷贝的情况,事实上,在Python 3中,dict.keys
、dict.values
和dict.items
都返回视图,并且Python 3中有许多其他方面都倾向于更多地使用迭代器,这使得似乎应该有一个朝向切片变得类似的运动。虽然itertools
有一个islice
函数可以进行迭代切片,但它比正常的切片更有限,而且不提供类似dict.keys
或dict.values
的视图功能。
此外,你可以使用切片赋值来修改原始列表,但切片本身是拷贝而不是视图,这是该语言的一个矛盾之处,似乎违反了Python之禅中所阐述的几个原则。
也就是说,你可以这样做:
>>> 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并未明确说明其切片为视图,但对于常规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),也不会为标准对象类型返回视图。”,但链接中的讨论并没有提到为什么要做关于切片视图的决定;事实上,对于原始帖子中列出的建议中的那个具体建议,大多数评论似乎是积极的。
是什么阻止了类似这样的东西在Python 3.0中的实现?Python 3.0专门设计为与Python 2.x不完全兼容,因此这将是实施这种设计变更的最佳时机,而且将来的Python版本中是否会有任何阻止这种变更的东西?