jar*_*arm 5 python list slice negative-number
我试图了解以下行为,并欢迎任何参考(尤其是官方文档)或评论。
让我们考虑一个列表:
>>> x = [1,2,3,4,5,6]
Run Code Online (Sandbox Code Playgroud)
这按预期工作
>>> x[-1:-4:-1]
[6, 5, 4]
Run Code Online (Sandbox Code Playgroud)
但我很惊讶以下是空的:
>>> x[0:-4:-1]
[]
Run Code Online (Sandbox Code Playgroud)
因此,我很惊讶以下不是空的
>>> x[0:-len(x)-1:-1]
> [1]
Run Code Online (Sandbox Code Playgroud)
特别是考虑到
>>> x[0:-len(x):-1]
[]
Run Code Online (Sandbox Code Playgroud)
还有那个
>>> x[0:-len(x)-1]
[]
Run Code Online (Sandbox Code Playgroud)
是空的。
有人向我指出了参考实现(给匿名捐助者的帽子),并发现从那里理解行为相当简单。完整地说,恕我直言,这种行为并不直观,但它仍然定义良好并且与参考实现相匹配。
有两个相关的 CPython 文件,即描述list_subscript和PySlice_AdjustIndices 的文件。当从列表中检索切片时(如本例所示),将调用list_subscript 。它调用PySlice_GetIndicesEx,后者又调用PySlice_AdjustIndices。现在PySlice_AdjustIndices包含简单的 if/then 语句,用于调整索引。最后它返回切片的长度。对于我们的例子,这些行
if (*stop < 0) {
*stop += length;
if (*stop < 0) {
*stop = (step < 0) ? -1 : 0;
}
}
Run Code Online (Sandbox Code Playgroud)
具有特别相关性。调整后,x[0:-len(x)-1:-1]变为x[0:-1:-1],长度返回1。然而,当x[0:-1:-1]通过调整时,它的x[0:len(x)-1:-1]长度变为0。换句话说,f(x) != f(f(x))在这种情况下。
有趣的是,PySlice_AdjustIndices中有以下注释:
/* this is harder to get right than you might think */
Run Code Online (Sandbox Code Playgroud)
最后,请注意,Python文档中没有描述有关情况的处理。
事实是
> x[-1:-4:-1]
[6, 5, 4]
> x[0:-4:-1]
[]
Run Code Online (Sandbox Code Playgroud)
不应该让你感到惊讶!很明显,您可以倒序将列表从最后一个元素切片到倒数第四个元素,但不能从第一个元素开始。
在
x[0:i:-1]
Run Code Online (Sandbox Code Playgroud)
的i必须是< -len(x)为了解决到索引< 0为结果含有的元素。slice 的语法很简单:
x[start:end:step]
Run Code Online (Sandbox Code Playgroud)
意味着,切片从start(here :) 开始0并在 end(或任何负数引用的索引)之前结束end。-len(x)解析为0,因此从长度为开始到0结束的切片不包含任何元素。,但是,将解析为实际的,从而产生从 开始的长度切片。00-len(x)-1-110
留end在向后切片空更直观地理解:
> l[2::-1]
[3, 2, 1]
> l[0::-1]
[1]
Run Code Online (Sandbox Code Playgroud)