为啥扩展切片分配不如常规切片分配灵活?

Posted

技术标签:

【中文标题】为啥扩展切片分配不如常规切片分配灵活?【英文标题】:Why is extended slice assignment less flexible than regular slice assignment?为什么扩展切片分配不如常规切片分配灵活? 【发布时间】:2018-06-06 16:26:31 【问题描述】:

根据extended slices 上的 Python 文档:

如果您有一个可变序列,例如列表或数组,您可以 分配或删除扩展切片,但有一些区别 在分配给扩展切片和常规切片之间。分配给一个 可以使用常规切片来改变序列的长度:

>>> a = range(3)
>>> a
[0, 1, 2]
>>> a[1:3] = [4, 5, 6]
>>> a
[0, 4, 5, 6]

扩展切片没有这么灵活。分配给扩展时 切片,语句右侧的列表必须包含 与它要替换的切片相同数量的项目:

>>> a = range(4)
>>> a
[0, 1, 2, 3]
>>> a[::2]
[0, 2]
>>> a[::2] = [0, -1]
>>> a
[0, 1, -1, 3]
>>> a[::2] = [0,1,2]
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: attempt to assign sequence of size 3 to extended slice of size 2

我不明白为什么“普通”切片方法有效但“扩展”切片方法不起作用。 “普通”切片和“扩展”切片的区别是什么?为什么“扩展”切片方法会失败?

【问题讨论】:

区别在于第三个参数,即步骤,如开头段落中所述。它失败是因为语句右侧的列表不包含与它要替换的切片 (2) 相同数量的项目 (3),这是您复制的文本所说的必需项。这就是为什么他们将其用作该描述的说明。不清楚您所说的 “为什么” 是什么意思。 【参考方案1】:

如果你试着想象一下,问题会更容易发现

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

适用于 4 项列表:

+---+---+---+---+   +   +---+
| a | b | c | d |       | ? |
+---+---+---+---+   +   +---+
  ^           ^           ^
+---+       +---+       +---+
| 0 |       | 1 |       | 2 |
+---+       +---+       +---+

我们正在尝试替换每三个值,但我们的列表不够长,所以如果我们继续进行下去,我们最终会得到某种奇怪的科学怪人列表,其中一些项目实际上并不存在.如果有人随后尝试访问 a[5] 并获得了 IndexError(即使 a[6] 正常工作),他们会真的感到困惑。

虽然从技术上讲,您可以通过将 a 扩展 1 来摆脱 a[::2] 的情况,但为了保持一致性,Python 禁止所有扩展切片分配,除非已经有一个可以存放值的地方。

常规切片的步幅始终为 1,因此不可能出现任何间隙,因此可以安全地允许分配。

【讨论】:

以上是关于为啥扩展切片分配不如常规切片分配灵活?的主要内容,如果未能解决你的问题,请参考以下文章

为啥通过切片分配到列表末尾之后不会引发 IndexError? [复制]

为啥切片 params 散列会对批量分配造成安全问题?

为啥可以将切片分配给空接口但不能将其强制转换为相同的空接口

Go 切片内存分配

当切片本身是张量流中的张量时如何进行切片分配

对张量流变量的切片分配