【问题标题】:Understanding negative steps in list slicing了解列表切片中的负面步骤
【发布时间】:2017-06-06 14:27:54
【问题描述】:

我正在尝试理解以下行为,并欢迎任何参考(尤其是官方文档)或 cmets。

让我们考虑一个列表:

>>> x = [1,2,3,4,5,6]

这按预期工作

>>> x[-1:-4:-1] 
[6, 5, 4]

但我很惊讶以下是空的:

>>>  x[0:-4:-1] 
[]

因此,我很惊讶以下不是空的

>>> x[0:-len(x)-1:-1]
> [1]

特别是考虑到

>>> x[0:-len(x):-1] 
[]

还有那个

>>> x[0:-len(x)-1] 
[]

是空的。

【问题讨论】:

    标签: python list slice negative-number


    【解决方案1】:

    事实

    > x[-1:-4:-1] 
    [6, 5, 4]
    > x[0:-4:-1] 
    []
    

    不应该让你感到惊讶!很明显,您可以从倒数的最后一个元素到倒数第四个元素对列表进行切片,但不能从第一个元素切片。

    x[0:i:-1]
    

    i 必须是 < -len(x) 才能解析为索引 < 0 以使结果包含一个元素。 slice 的语法很简单:

    x[start:end:step]
    

    表示,切片从start(此处为:0)开始,并在之前end(或任何负数end 引用的索引)结束。 -len(x) 解析为0,因此从0 开始并以0 结束的切片长度为0,不包含任何元素。但是,-len(x)-1 将解析为实际的 -1,从而生成从 0 开始的长度为 1 的切片。

    在后向切片中将end留空更直观理解:

    > l[2::-1]
    [3, 2, 1]
    > l[0::-1]
    [1]
    

    【讨论】:

    • 感谢您的回答,但我还是不明白。您写道 -len(x)-1 解析为 -1。您能否详细说明它如何解析为 -1 以及为什么,因为对我来说 -len(x)-1 似乎等于 -7。是否与 x[0] == x[-len(x)] 的事实有关?
    • 是的。任何用作序列seq 上的索引或切片参数的负数-i 都会解析为实际索引len(seq) - i。因此,对于长度为6listl[0:-7:-1] 是从0-1 (6 - 7) 的后向切片。对于包含第一个元素(索引 0)的任何向后切片,您必须选择 end < -len(seq) 或将其留空:seq[start::-1]
    【解决方案2】:

    我被指向了参考实现(匿名恩人的帽子),发现从那里理解行为相当简单。完整地说,恕我直言,这种行为是不直观的,但它仍然定义良好并且与参考实现相匹配。

    两个 CPython 文件是相关的,即描述 list_subscriptPySlice_AdjustIndices 的文件。在这种情况下,从列表中检索切片时,会调用 list_subscript。它调用 PySlice_GetIndicesEx,后者又调用 PySlice_AdjustIndices。 现在 PySlice_AdjustIndices 包含简单的 if/then 语句,用于调整索引。最后它返回切片的长度。就我们而言,这些行

    if (*stop < 0) {
        *stop += length;
        if (*stop < 0) {
            *stop = (step < 0) ? -1 : 0;
        }
    }
    

    具有特别的相关性。调整后x[0:-len(x)-1:-1]变成x[0:-1:-1],返回长度1。但是,当x[0:-1:-1]被传递给调整时,它变成了长度为0的x[0:len(x)-1:-1]。也就是说,在这种情况下,f(x) != f(f(x))

    有趣的是,PySlice_AdjustIndices中有如下评论:

    /* this is harder to get right than you might think */
    

    最后请注意,pythondocs中没有描述问题情况的处理。

    【讨论】:

      【解决方案3】:
      x[0:-4:-1]
      

      使用 -1 步从 0 到 2?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-07
        • 1970-01-01
        • 2019-08-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多