Python *中的默认切片索引是什么*?

时间:2012-09-20 22:25:59

标签: python slice

来自python文档docs.python.org/tutorial/introduction.html#strings

  

切片索引具有有用的默认值;省略的第一个索引默认为零,省略的第二个索引默认为要切片的字符串的大小。

对于标准情况,这很有道理:

>>> s = 'mystring'
>>> s[1:]
'ystring'
>>> s[:3]
'mys'
>>> s[:-2]
'mystri'
>>> s[-1:]
'g'
>>> 

到目前为止,这么好。但是,使用负步长值似乎表明默认值略有不同:

>>> s[:3:-1]
'gnir'
>>> s[0:3:-1]
''
>>> s[2::-1]
'sym'

很好,如果步骤为负,则默认值相反。省略的第一个索引默认为要切片的字符串的大小,省略的第二个索引默认为零:

>>> s[len(s):3:-1]
'gnir'

看起来不错!

>>> s[2:0:-1]
'sy'

糟糕。错过了'我'。

然后是每个人最喜欢的字符串反向语句。它很甜蜜:

>>> s[::-1]
'gnirtsym'

然而:

>>> s[len(s):0:-1]
'gnirtsy'

切片永远不会包含切片中第二个索引的值。我可以看到这样做的一致性。

所以我认为我开始理解切片在各种排列中的行为。但是,我觉得第二个索引有点特殊,并且负步骤的第二个索引的默认值实际上不能用数字来定义。

任何人都可以简明地定义可以解释所提供示例的默认切片索引吗?文档将是一个巨大的优势。

8 个答案:

答案 0 :(得分:8)

实际上没有任何默认值;省略的值是专门处理的。

但是,在每种情况下,省略的值恰好以与None完全相同的方式处理。这意味着,除非您正在攻击解释器(或使用parserast等模块),否则您可以假装默认值为None(如递归的答案所示),并且您总会得到正确的答案。

引用的非正式文档并不十分准确 - 这对于那些本来应该成为教程一部分的内容来说是合理的。对于真正的答案,您必须转向参考文档。

对于2.7.3,Sequence Types描述了注释3,4和5中的切片。

[i:j]

  

...如果省略 i None,请使用0。如果省略 j None,请使用len(s)

对于[i:j:k]

  

如果忽略 i j None,它们将成为“结束”值(结束取决于 k的符号)。注意, k 不能为零。如果 k None,则会将其视为1

对于3.3,Sequence Types具有与2.7.3完全相同的措辞。

答案 1 :(得分:4)

reference documentation for sequence types中的注释详细解释了这一点:

  

(5.) s i j 的切片<步骤 k 被定义为索引为x = i + n*k的项目序列为0 <= n < (j-i)/k。换句话说,索引是ii+ki+2*ki+3*k等等,在达到 j 时停止(但从不包括Ĵ)。如果 i j 大于len(s),请使用len(s)。如果省略 i j None,它们将成为“结束”值(结束取决于 k 的符号) 。注意, k 不能为零。如果 k None,则会将其视为1

所以你可以得到以下行为:

>>> s = "mystring"
>>> s[2:None:-1]
'sym'

答案 2 :(得分:4)

我没有任何文档,但我认为默认值为[None:None:None]

>>> "asdf"[None:None:None]
'asdf'
>>> "asdf"[None:None:-1]
'fdsa'

答案 3 :(得分:3)

结束值总是独占,因此0结束值表示包括索引1但不包括0.使用None代替(因为负数具有不同的含义):

>>> s[len(s)-1:None:-1]
'gnirtsym'

注意起始值;最后一个字符索引位于len(s) - 1;你也可以拼写为-1(因为负数是相对于长度来解释的):

>>> s[-1:None:-1]
'gnirtsym'

答案 4 :(得分:1)

实际上这是合乎逻辑的......

如果查看结束值,它总是指向最后一个索引之后的索引。 因此,使用0作为结束值,意味着它直到索引1处的元素。因此,您需要省略该值..以便它返回您想要的字符串。

>>> s = '0123456789'
>>> s[0], s[:0]
('0', '')
>>> s[1], s[:1]
('1', '0')
>>> s[2], s[:2]
('2', '01')
>>> s[3], s[:3]
('3', '012')
>>> s[0], s[:0:-1]
('0', '987654321')

答案 5 :(得分:1)

有用了解您是否正在实施__getslice__j默认为sys.maxsizehttps://docs.python.org/2/reference/datamodel.html#object.getslice

>>> class x(str):
...   def __getslice__(self, i, j):
...     print i
...     print j
...
...   def __getitem__(self, key):
...     print repr(key)
...
>>> x()[:]
0
9223372036854775807
>>> x()[::]
slice(None, None, None)
>>> x()[::1]
slice(None, None, 1)
>>> x()[:1:]
slice(None, 1, None)
>>> import sys
>>> sys.maxsize
9223372036854775807L

答案 6 :(得分:0)

有很好的答案,最好的答案被选为接受的答案,但如果您正在寻找一种方法来解决切片的默认值,那么将列表想象成有两端会很有帮助。从 HEAD 开始,然后是第一个元素,依此类推,直到最后一个元素之后的 TAIL 结束。

现在回答实际问题:

切片有两个默认值

  1. step 为 +ve 时的默认值

    0:TAIL:+ve 步

  2. step 为 -ve 时的默认值

    HEAD:-1:-ve 步骤

答案 7 :(得分:0)

好问题。我以为我知道切片是如何工作的,直到我读到这篇文章。虽然您的问题标题询问了“默认切片索引”并且 abarnet、Martijn 和其他人已经回答了这个问题,但您的帖子正文表明您的真正问题是“切片是如何工作的”。所以,我会尝试一下..

说明

以您的示例 s = “mystring” 为例,您可以想象一组正指数和负指数。

 m  y  s  t  r  i  n  g
 0  1  2  3  4  5  6  7 <- positive indices
-8 -7 -6 -5 -4 -3 -2 -1 <- negative indices

我们选择 s[i:j:k] 形式的切片。逻辑会根据 k 是正数还是负数而变化。我将算法描述如下。

if k is empty, set k = 1

if k is positive:
  move right, from i (inclusive) to j (exclusive) stepping by abs(k)
  if i is empty, start from the left edge
  if j is empty, go til the right edge

if k is negative:
  move left, from i (inclusive) to j (exclusive) stepping by abs(k)
  if i is empty, start from the right edge
  if j is empty, go til the left edge

(请注意,这并不完全是伪代码,因为我想让它更易于理解。)


示例

>>> s[:3:]
'mys'

这里,k 为空,因此我们将其设置为 1。然后由于 k 为正,我们从 i 向右移动到 j。由于 i 是空的,我们从左边缘开始,选择直到但不包括索引 3 处的元素的所有内容。

>>> s[:3:-1]
'gnir'

这里,k 是负数,所以我们将 lefti 移到 j。由于 i 是空的,我们从 边缘开始,选择直到但不包括索引 3 处的元素的所有内容。

>>> s[0:3:-1]
''

这里,k 是负数,所以我们将 lefti 移到 j。由于索引 3 不在索引 0 的左侧,因此没有选择任何元素,我们返回空字符串。