为什么在Python 3中,切片仍然是副本而不是视图?

7 浏览
0 Comments

为什么在Python 3中,切片仍然是副本而不是视图?

在我评论了这个答案之后,我才注意到在Python 3中,切片返回的是被切片对象的浅拷贝,而不是视图。为什么仍然如此?即使不考虑numpy在切片中使用视图而不是拷贝的情况,事实上,在Python 3中,dict.keysdict.valuesdict.items都返回视图,并且Python 3中有许多其他方面都倾向于更多地使用迭代器,这使得似乎应该有一个朝向切片变得类似的运动。虽然itertools有一个islice函数可以进行迭代切片,但它比正常的切片更有限,而且不提供类似dict.keysdict.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版本中是否会有任何阻止这种变更的东西?

0