JAB*_*JAB 50 python language-design slice python-3.x
正如我在评论这个答案后才注意到的那样,Python 3中的切片返回了他们正在切片而不是视图的浅层副本.为什么仍然如此?即使撇开观点numpy的的使用,而不是切片的副本,事实证明dict.keys
,dict.values
和dict.items
在Python 3所有回报的意见,并有走向更大的使用迭代器面向Python 3中的其他许多方面,使它看起来将会有些切片变得相似的运动.itertools
确实有一个islice
函数可以进行迭代切片,但是它比普通切片更有限,并且不提供沿着dict.keys
或者行的视图功能dict.values
.
同样,你可以使用赋值给切片来修改原始列表,但切片本身就是副本而不是视图,这是语言的一个矛盾方面,似乎它违反了Python的Zen中所说明的几个原则.
也就是说,你可以做的事实
>>> a = [1, 2, 3, 4, 5]
>>> a[::2] = [0, 0, 0]
>>> a
[0, 2, 0, 4, 0]
Run Code Online (Sandbox Code Playgroud)
但不是
>>> a = [1, 2, 3, 4, 5]
>>> a[::2][0] = 0
>>> a
[0, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)
或类似的东西
>>> 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]
Run Code Online (Sandbox Code Playgroud)
似乎有点武断/不受欢迎.
我知道http://www.python.org/dev/peps/pep-3099/以及它所说的"切片和扩展切片不会消失的部分(即使可以替换API __getslice__
和__setslice__
API)"他们是否会返回标准对象类型的视图."但是链接的讨论没有提到为什么做出关于切片视图的决定; 事实上,原始帖子中列出的建议中对该特定建议的大多数评论似乎都是积极的.
是什么阻止了这样的东西在Python 3.0中实现,Python 3.0专门设计为不与Python 2.x严格向后兼容,因此可能是实现这种设计变更的最佳时机,并且有什么可能的在未来的Python版本中阻止它?
Sin*_*ion 11
同样,您可以使用赋值给切片来修改原始列表,但切片本身就是副本而不是视图.
嗯..那不太对; 虽然我可以看到你怎么想.在其他语言中,切片分配,例如:
a[b:c] = d
Run Code Online (Sandbox Code Playgroud)
相当于
tmp = a.operator[](slice(b, c)) # which returns some sort of reference
tmp.operator=(d) # which has a special meaning for the reference type.
Run Code Online (Sandbox Code Playgroud)
但在python中,第一个语句实际上转换为:
a.__setitem__(slice(b, c), d)
Run Code Online (Sandbox Code Playgroud)
也就是说,项目赋值实际上是在python中特别识别的,具有特殊含义,与项目查找和赋值分开; 他们可能是无关的.这与python作为一个整体是一致的,因为python没有像C/C++中的"lvalues"那样的概念; 没有办法重载赋值运算符本身; 仅当赋值的左侧不是普通标识符时的特定情况.
假设列表确实有视图; 你试图使用它:
myView = myList[1:10]
yourList = [1, 2, 3, 4]
myView = yourList
Run Code Online (Sandbox Code Playgroud)
在python之外的语言中,可能有一种方法可以yourList
推进myList
,但在python中,由于名称myView
显示为一个简单的标识符,它只能表示一个变量的assignemnt; 视图丢失了.
嗯,看来我发现了视图决定背后的很多推理,通过以http://mail.python.org/pipermail/python-3000/2006-August/003224.html开始的线程(它主要是关于切片字符串,但线程中至少有一封电子邮件提到了可变对象(例如列表),以及来自以下内容的一些内容:
http://mail.python.org/pipermail/python-3000/2007-February/005739.html
http://mail.python.org/pipermail/python-dev/2008-May/079692.html和以下电子邮件线程中的邮件
看起来,对于基础 Python 来说,切换到这种风格的优势将被引发的复杂性和各种不良的边缘情况所抵消。那好吧。
...然后,当我开始想知道是否有可能将当前的slice
对象处理方式替换为可迭代形式 la itertools.islice
,就像zip
、map
等所有返回可迭代对象而不是 Python 3 中的列表一样,我开始意识到所有意外的行为以及由此可能产生的问题。看来目前这可能是一个死胡同。
从好的方面来说,numpy 的数组相当灵活,因此在可能需要这种事情的情况下,使用一维 ndarray 代替列表并不会太难。然而,ndarrays 似乎不支持使用切片在数组中插入其他项目,就像 Python 列表一样:
>>> a = [0, 0]
>>> a[:1] = [2, 3]
>>> a
[2, 3, 0]
Run Code Online (Sandbox Code Playgroud)
我认为 numpy 的等价物应该是这样的:
>>> 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])
Run Code Online (Sandbox Code Playgroud)
稍微复杂一点的情况:
>>> a = [1, 2, 3, 4]
>>> a[1:3] = [0, 0, 0]
>>> a
[1, 0, 0, 0, 4]
Run Code Online (Sandbox Code Playgroud)
相对
>>> a = np.array([1, 2, 3, 4])
>>> a = np.hstack((a[:1], [0, 0, 0], a[3:]))
>>> a
array([1, 0, 0, 0, 4])
Run Code Online (Sandbox Code Playgroud)
当然,上面的 numpy 示例不会像常规 Python 列表扩展那样将结果存储在原始数组中。
归档时间: |
|
查看次数: |
5685 次 |
最近记录: |