为什么Python 3中的切片仍会复制而不是视图? [英] Why are slices in Python 3 still copies and not views?

查看:219
本文介绍了为什么Python 3中的切片仍会复制而不是视图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正如我现在在评论此答案之后才注意到的那样, Python 3中的切片返回所切片内容的浅表副本,而不是视图.为什么仍然如此?即使将numpy的视图用法而不是副本用于切片,撇开dict.keysdict.valuesdict.items都返回Python 3中的视图这一事实,并且Python 3还有许多其他方面旨在更好地使用迭代器,似乎会朝着切片变得相似的方向发展. itertools确实具有islice函数,该函数可以进行迭代切片,但是比普通切片更受限制,并且不提供沿dict.keysdict.values的视图功能.

As I only now noticed after commenting on this answer, slices in Python 3 return shallow copies of whatever they're slicing rather than views. Why is this still the case? Even leaving aside numpy's usage of views rather than copies for slicing, the fact that dict.keys, dict.values, and dict.items all return views in Python 3, and that there are many other aspects of Python 3 geared towards greater use of iterators, makes it seem that there would have been a movement towards slices becoming similar. itertools does have an islice function that makes iterative slices, but that's more limited than normal slicing and does not provide view functionality along the lines of dict.keys or dict.values.

同样,您可以对切片使用赋值来修改原始列表,但是切片本身是副本而不是视图,这是该语言的一个矛盾方面,似乎违反了 Python的禅宗.

As well, the fact that you can use assignment to slices to modify the original list, but slices are themselves copies and not views, is a contradictory aspect of the language and seems like it violates several of the principles illustrated in the Zen of Python.

也就是说,你可以做的事实

That is, the fact you can do

>>> 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]

似乎有些武断/不受欢迎.

Seems somewhat arbitrary/undesirable.

我知道 http://www.python.org/dev/peps/pep-3099/及其表示切片和扩展切片不会消失(即使__getslice____setslice__ API可能会消失)的部分,也不会返回标准的视图对象类型.",但链接的讨论未提及为何做出关于切片视图的决定;实际上,在原始帖子中列出的建议中,对该特定建议的大多数评论似乎都是肯定的.

I'm aware of http://www.python.org/dev/peps/pep-3099/ and the part where it says "Slices and extended slices won't go away (even if the __getslice__ and __setslice__ APIs may be replaced) nor will they return views for the standard object types.", but the linked discussion provides no mention of why the decision about slicing with views was made; in fact, the majority of the comments on that specific suggestion out of the suggestions listed in the original post seemed to be positive.

是什么阻止了类似的事情在Python 3.0中实现,它是专门为与Python 2.x不严格向后兼容而设计的,因此这是实现这种设计更改的最佳时机,并且在那里有什么可能在将来的Python版本中阻止它吗?

What prevented something like this from being implemented in Python 3.0, which was specifically designed to not be strictly backwards-compatible with Python 2.x and thus would have been the best time to implement such a change in design, and is there anything that may prevent it in future versions of Python?

推荐答案

好吧,看来我发现了view决策背后的很多原因,都是以

Well it seems I found a lot of the reasoning behind the views decision, going by the thread starting with http://mail.python.org/pipermail/python-3000/2006-August/003224.html (it's primarily about slicing strings, but at least one e-mail in the thread mentions mutable objects like lists), and also some things from:

http://mail.python.org/pipermail/python-3000/2007-February/005739.html
http://mail.python.org/pipermail/python-dev /2008-May/079692.html 以及该主题中的后续电子邮件

http://mail.python.org/pipermail/python-3000/2007-February/005739.html
http://mail.python.org/pipermail/python-dev/2008-May/079692.html and following e-mails in the thread

看起来为基本的Python切换到这种样式的优势将大大地被引发的复杂性和各种不良边缘情况所抵消.哦,好吧.

Looks like the advantages of switching to this style for base Python would be vastly outweighed by the induced complexity and various undesirable edge cases. Oh well.

...然后,我开始怀疑是否可以用可迭代的形式(例如zipmap等)替换当前的slice对象使用可迭代形式的可能性.所有函数都返回可迭代函数,而不是Python 3中的列表,我开始意识到所有意外行为和由此可能产生的问题.看来这可能是目前的死胡同.

...And as I then started wondering about the possibility of just replacing the current way slice objects are worked with with an iterable form a la itertools.islice, just as zip, map, etc. all return iterables instead of lists in Python 3, I started realizing all the unexpected behavior and possible problems that could come out of that. Looks like this might be a dead end for now.

从好的方面来说,numpy的数组非常灵活,因此在可能需要这种事情的情况下,使用一维ndarray而不是列表并不难.但是,似乎ndarrays不支持使用切片在数组中插入其他项,就像Python列表一样:

On the plus side, numpy's arrays are fairly flexible, so in situations where this sort of thing might be necessary, it wouldn't be too hard to use one-dimensional ndarrays instead of lists. However, it seems ndarrays don't support using slicing to insert additional items within arrays, as happens with Python lists:

>>> a = [0, 0]
>>> a[:1] = [2, 3]
>>> a
[2, 3, 0]

我认为numpy等效项应该是这样的:

I think the numpy equivalent would instead be something like this:

>>> a = np.array([0, 0])  # or a = np.zeros([2]), but that's not important here
>>> a = np.hstack(([2, 3], a[1:]))
>>> a
array([2, 3, 0])

稍微复杂一点的情况:

>>> a = [1, 2, 3, 4]
>>> a[1:3] = [0, 0, 0]
>>> a
[1, 0, 0, 0, 4]

>>> a = np.array([1, 2, 3, 4])
>>> a = np.hstack((a[:1], [0, 0, 0], a[3:]))
>>> a
array([1, 0, 0, 0, 4])

当然,上面的numpy示例不会像常规Python列表扩展那样将结果存储在原始数组中.

And, of course, the above numpy examples don't store the result in the original array as happens with the regular Python list expansion.

这篇关于为什么Python 3中的切片仍会复制而不是视图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆