【问题标题】:I don't understand slicing with negative bounds in Python. How is this supposed to work?我不明白 Python 中的负边界切片。这应该如何工作?
【发布时间】:2010-10-04 07:55:42
【问题描述】:

我是 Python 的新手,并且在我的书中遇到了以下示例,但没有很好地解释。这是我从解释器打印出来的:

>>> s = 'spam'
>>> s[:-1]
'spa'

为什么没有开始边界和'-1' 的切片会返回除最后一个元素之外的所有元素?调用s[0:-1] 在逻辑上与调用s[:-1] 相同吗?它们都返回相同的结果。但我不确定python到底在做什么。任何帮助将不胜感激。

【问题讨论】:

    标签: python slice


    【解决方案1】:

    是的,调用s[0:-1] 与调用s[:-1] 完全相同。

    在 python 中使用负数作为索引返回列表右侧的第 n 个元素(与通常的左侧相反)。

    所以如果你有一个这样的列表:

    myList = ['a', 'b', 'c', 'd', 'e']
    print myList[-1] # prints 'e'
    

    打印语句将打印“e”。

    一旦你理解了这一点(你可能已经明白了,不完全清楚这是否是你感到困惑的事情之一),我们就可以开始讨论切片了。

    我将假设您了解沿 myList[2:4] 行(将返回 ['c', 'd'])的切片的基础知识,并直接跳入其中一侧留空的切片符号。

    正如您在帖子中所怀疑的那样,myList[:index]myList[0:index] 完全相同。

    这也适用于其他方式,顺便说一句...myList[index:]myList[index:len(myList)] 相同,并将返回列表中所有元素的列表,从 index 开始直到结束(例如print myList[2:] 将打印['c', 'd', 'e'])。

    作为第三个注释,你甚至可以在 no 索引的地方做print myList[:],这基本上会返回整个列表的副本(相当于myList[0:len(myList)],返回['a' , 'b', 'c', 'd', 'e'])。如果您认为 myList 会在某个时候发生变化,但您希望将其副本保持在当前状态,这可能会很有用。

    如果您还没有这样做,我会发现只是在 Python 解释器中乱搞对理解这些事情有很大帮助。我推荐IPython

    【讨论】:

    • 谢谢!这说明了一切。
    • @Lawrence:在代码块之后的第二段中,mylist[2, 4] 应该是 myList[2:4]。 (抱歉,我没有足够的代表来编辑。)
    • @Pourquoi Litytestdata:打错字很好,现在已修复。
    • @LawrenceJohnston,假设我有一个字符串 a='0123456789' 使用 a[-1:-4] 返回空?你能帮忙解释一下吗?它不应该至少打印 -1 索引,因为它是包容性的吗?
    【解决方案2】:
    >>> l = ['abc', 'def', 'ghi', 'jkl', 'mno', 'pqr', 'stu', 'vwx', 'yz&']
    
    # I want a string up to 'def' from 'vwx', all in between
    # from 'vwx' so -2;to 'def' just before 'abc' so -9; backwards all so -1.
    >>> l[-2:-9:-1]
    ['vwx', 'stu', 'pqr', 'mno', 'jkl', 'ghi', 'def']
    
    # For the same 'vwx' 7 to 'def' just before 'abc' 0, backwards all -1
    >>> l[7:0:-1]
    ['vwx', 'stu', 'pqr', 'mno', 'jkl', 'ghi', 'def']
    

    请不要对列表无精打采。

    1. 首先写入第一个元素。您可以使用正或负索引 为了那个原因。我很懒,所以我使用正数,少一杆(低于 7,或 -3 开始)。
    2. 要停止的位置之前的元素的索引。 同样,您可以为此使用正或负索引(低于 2 或 -8 表示停止)。
    3. 这里的标志很重要;当然-向后;你知道的步幅的价值。 步幅是一个具有大小和方向的“向量”(低于 -1,全部向后)。

      l = [0,1,2,3,4,5,6,7,8,9]
      l[7:2:-1], l[-3:2:-1], [-3:-8:-1],l[7:-8:-1]
      

      所有结果都是[7, 6, 5, 4, 3]

    【讨论】:

      【解决方案3】:

      负索引从末尾开始计算,因此 s[:-1] 等价于 s[:len(s)-1] 并且 s[-1] 是最后一个元素。

      【讨论】:

        【解决方案4】:

        关键的一点是,python 索引应该被认为是指向列表中条目之间的空间的指针,而不是指向元素本身的指针。因此,0 指向开头,1 指向第一个和第二个之间,... 和 n 指向第 n 个和 (n+1)st 之间。

        因此 l[1:2] 为您提供了一个仅包含元素 l[1] 的列表,因为它为您提供了两个指针之间的所有内容。

        类似地,负索引指向元素之间,但这次从后面开始计数,所以 -1 指向最后一个元素和倒数第二个元素之间,所以 [0:-1] 指的是一个不包括最后一个。

        作为语法糖,您可以从开头省略 0,或者实际上是结尾,因此 l[n:] 指的是从 l[n] 到结尾的所有内容(如果 n>=len(l) 则它返回空列表)。

        【讨论】:

        • "因此 l[1:2] 只给你元素 l[1]" - l[1:2] 返回一个只包含元素 l[1] 的列表。这与元素 l[1] 不同。您可以对其进行编辑以免混淆读者。
        • l[n:] 指的是一个空列表 - 一个“在最后一个元素之后”。这个也可以纠正:-)
        • (其实对于l[n:]我不是说n=len(l),但是你说得对,不清楚……两者都修复了。
        【解决方案5】:

        是的,调用s[0:-1] 在逻辑上与s[:-1] 相同,因为切片最好定义为:

        [beginning_index:ending_index]
        

        Python 允许您省略 0,因为这可以让您的代码更简洁。

        【讨论】:

          【解决方案6】:

          如果我们想从字符串的后端打印,我们可以使用负索引。索引从 -1 开始。

          示例:s = 'hello world'

          s[-11:-1] = '你好世界' s[-1:-11] = '' // 起始值应该更低(即,在这种情况下,-1 大于 -11)如果它更大,则不会打印任何内容。

          【讨论】:

          • 你应该这样做:s[-1:-11:-1],最后一个索引表示步骤
          【解决方案7】:

          我将解决其他人遗漏的一点:

          根据我们对切片的了解,我们如何解释这个负指数?

          一般来说,当我们进行切片时,我们会谈论 [inclusive,exclusive] 边界。所以

          A = [1,3,4,6]
          A[1:3] # will give us 3-1 = 2 elements, index 1 and 2 => [3,4]
          

          所以当我们在切片中有一个负索引时,A[1:-1],这意味着我们有A[1:len(A)-1] = A[1:3],这又给了我们索引 1 和 2,因此是[3,4]

          请注意,即使列表的长度为 4,它的最后一个索引也是 3,因此这个 -1 表示法在这里可以工作。另请注意,如果您有将负索引作为变量的代码,那么您需要手动检查 0,因为 A[:-0] == A[:0] == [] `

          【讨论】:

            猜你喜欢
            • 2016-03-30
            • 1970-01-01
            • 1970-01-01
            • 2023-02-02
            • 1970-01-01
            • 2014-02-03
            • 2021-11-03
            • 1970-01-01
            相关资源
            最近更新 更多