Python切片运算符[开始:停止:步骤]

beq87vna  于 2023-02-18  发布在  Python
关注(0)|答案(2)|浏览(86)

我了解Python中切片操作符的概念,但我对"停止"有点困惑。
例如:

lst = [1,2,3,4,5]
print(lst[0:4])

我认为答案应该是[1,2,3,4,5],因为它将停止在索引4上,即元素5。然而,正确的答案应该是[1,2,3,4]
有什么解释?

y1aodyip

y1aodyip1#

Python的范围被称为“exclusive”,因为索引为stop的元素被从结果中 * 排除 *。
之所以选择这种行为,是因为互斥(而不是包含)上界可以很好地处理0索引序列,Python在其所有核心数据序列类型(listtuplestrbytesbytearrayarray.array)中都使用了0索引序列。
记住这句话是一回事,但理解它为什么有意义又是另一回事!
一般来说,数组的0索引会让你把数组中的任何位置当作光标,光标位于数组元素之间。这种数组设计一开始看起来有点不寻常,但实际上是一种非常符合人体工程学的方式。
考虑阵列:

values:    a   b   c   d   e   f
indexes:   0   1   2   3   4   5

我们被教导从0开始计数,所以第一个位置是索引0,第二个位置是索引1,以此类推,直到最后一个位置,索引len(data) - 1
我们可以将此模式形象化为描述光标位于感兴趣元素 * 之前 * 的位置:

index 0: | a   b   c   d   e   f
index 1:   a | b   c   d   e   f
index 2:   a   b | c   d   e   f
index 3:   a   b   c | d   e   f
index 4:   a   b   c   d | e   f
index 5:   a   b   c   d   e | f

将光标位置编号为比元素位置小1是此心理模型的有意反映。
用这种方式设计数组有历史上的原因,与内存地址和指针有关。但是除非你用C或C++编程,否则你可以忽略这些原因,因为它作为序列的抽象模型也很好用。你可以看到here是支持0索引的一个著名的美学论点。
一旦我们接受了0索引是舒适和自然的,这反过来又影响了我们对 ranges 的看法,因为现在数组中最后一个元素的索引是index len(data) - 1,所以如果我们想使用 * included * 上限来选择整个数组,我们就必须把range写成0 : len(data) - 1,这是丑陋和笨拙的。所以使用 exclusive 上限允许我们写0 : len(data).现在范围的上限与数据的长度很好地一致,同时允许我们使用0索引.这种行为出现在range函数中,:语法以及X1 M14 N1 X语法表示的X1 M13 N1 X类。
此外,互斥上限强化了这样一个概念,即从0开始的索引是位于当前元素 * 之前 * 的游标。
考虑一个选择cde的范围,如果你在所选值周围画一个框,你会注意到“框”的最右边/最上面的“边缘”实际上是“超过"最终值:

values:    a   b | c   d   e | f
indexes:   0   1 | 2   3   4 | 5
                 |-----------|

如果我们考虑游标,上界位于 * ef之间,我们知道索引为5。我们不会 * 超过 * 上界;我们在 * 之前停止。因此,将该范围写为2:5是完全自然的--我们在索引2之前开始 *,包括索引34,然后在到达索引5之前停止。如果我们将该范围写为2:4,这将导致将索引解释为游标的不一致,这会让人很困惑。
最后,用户chepner在一条评论中指出,互斥范围导致序列切片的一个优雅属性。对于序列x和索引a < b < c,则x[a:b] + x[b:c] == x[a:c]。当范围互斥时,该属性 * 不 * 保留。作为练习,使用“游标”模型来说服自己,当范围是独占的时,该属性被保留,而当范围是包含的时,该属性被破坏。

csbfibhn

csbfibhn2#

此可视化可能有助于:

关于Python列表切片的Here's a very useful网页。

相关问题