Why are slices in Python 3 still copies and not views?
正如我在评论完这个答案后才注意到的,python3中的切片返回了它们正在切片的内容的浅拷贝,而不是视图。为什么还是这样?即使不考虑numpy对视图的使用而不是用于切片的副本,事实上
此外,您可以使用赋值来切片修改原始列表,但切片本身是副本,而不是视图,这是语言的一个矛盾方面,似乎违反了Python禅中说明的几个原则。
也就是说,事实上你可以
1 2 3 4 | >>> a = [1, 2, 3, 4, 5] >>> a[::2] = [0, 0, 0] >>> a [0, 2, 0, 4, 0] |
但不是
1 2 3 4 | >>> a = [1, 2, 3, 4, 5] >>> a[::2][0] = 0 >>> a [0, 2, 3, 4, 5] |
或者类似的
1 2 3 4 5 6 7 8 9 | >>> 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/和它所说的"切片和扩展切片不会消失(即使可以替换
是什么阻止了类似这样的事情在Python3.0中实现,而Python3.0是专门设计为不与Python2.x严格向后兼容的,因此是实现这种设计更改的最佳时机,在将来的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.
隐马尔可夫模型。。这不太对,尽管我能看出你是怎么想的。在其他语言中,切片分配,类似于:
1 | a[b:c] = d |
等于
1 2 | tmp = a.operator[](slice(b, c)) # which returns some sort of reference tmp.operator=(d) # which has a special meaning for the reference type. |
但是在python中,第一条语句实际上被转换为:
1 | a.__setitem__(slice(b, c), d) |
也就是说,在python中,一个项目分配实际上是被特别地识别出来的,具有特殊的意义,与项目查找和分配分开;它们可能是无关的。这与Python作为一个整体是一致的,因为Python没有类似于C/C++中的"LVales"的概念;无法赋值赋值运算符本身;只有特定的情况,当赋值的左边不是一个简单的标识符时。
假设列表确实有视图,并且您尝试使用它:
1 2 3 | myView = myList[1:10] yourList = [1, 2, 3, 4] myView = yourList |
在除python之外的语言中,可能有一种方法可以将
好吧,看起来我发现了很多视图决策背后的原因,从http://mail.python.org/pipermail/python-3000/2006-august/003224.html开始(它主要是关于字符串切片,但线程中至少有一封电子邮件提到了列表等可变对象),以及以下内容:
http://mail.python.org/pipermail/python-3000/2007-2月/005739.htmlhttp://mail.python.org/pipermail/python-dev/2008-may/079692.html以及线程中的以下电子邮件
看起来,为基本python切换到这种风格的优势将被所引起的复杂性和各种不需要的边缘情况大大抵消。哦,好吧。
…然后,当我开始考虑是否可以用一个可迭代的形式来代替当前的方法来处理
另一方面,numpy的数组相当灵活,因此在需要这种类型的情况下,使用一维的ndarrays而不是列表并不难。但是,Ndarrays似乎不支持使用切片在数组中插入其他项,就像在python列表中那样:
1 2 3 4 | >>> a = [0, 0] >>> a[:1] = [2, 3] >>> a [2, 3, 0] |
我认为麻木的等价物应该是这样的:
1 2 3 4 | >>> 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]) |
稍微复杂一点的情况:
1 2 3 4 | >>> a = [1, 2, 3, 4] >>> a[1:3] = [0, 0, 0] >>> a [1, 0, 0, 0, 4] |
对战
1 2 3 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]) |
当然,上面这些麻木的示例并不像常规的python列表扩展那样将结果存储在原始数组中。