18

从 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'

哎呀。错过了那个'm'。

然后就是大家最喜欢的字符串反转语句了。甜蜜的是:

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

然而:

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

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

所以我想我开始了解 slice 在各种排列中的行为。但是,我感觉第二个索引有些特殊,并且负步长的第二个索引的默认值实际上不能用数字来定义。

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

4

8 回答 8

17

实际上没有任何默认值。省略的值会被特殊处理。

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

引用的非正式文档不是很准确——这对于作为教程一部分的内容来说是合理的。对于真正的答案,您必须求助于参考文档。

对于 2.7.3,序列类型在注释 3、4 和 5 中描述了切片。

对于[i:j]

…如果省略iNone或,请使用0。如果省略jNone或,请使用len(s)

对于[i:j:k]

如果ij被省略 or None,它们将成为“结束”值(结束取决于k的符号)。注意,k不能为零。如果kNone,则将其视为1

对于 3.3,序列类型的措辞与 2.7.3 完全相同。

于 2012-09-21T00:42:56.830 回答
5

结束值总是排他的,因此 0 结束值意味着包括索引 1 但不包括 0。使用 None 代替(因为负数具有不同的含义):

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

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

>>> s[-1:None:-1]
'gnirtsym'
于 2012-09-20T22:42:34.500 回答
4

序列类型的参考文档中的注释详细解释了这一点:

(5.)从ij步骤k的s切片被定义为具有索引的项目序列,使得。换句话说,索引是, , ,等等,当达到j时停止(但从不包括j)。如果ij大于,则使用。如果ij被省略 or ,它们将成为“结束”值(结束取决于k的符号)。注意,k不能为零。如果kx = i + n*k0 <= n < (j-i)/kii+ki+2*ki+3*klen(s)len(s)NoneNone, 它被当作1.

因此,您可以获得以下行为:

>>> s = "mystring"
>>> s[2:None:-1]
'sym'
于 2012-09-20T22:28:37.033 回答
4

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

>>> "asdf"[None:None:None]
'asdf'
>>> "asdf"[None:None:-1]
'fdsa'
于 2012-09-20T22:31:23.133 回答
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')
于 2012-09-20T22:31:58.017 回答
1

了解您是否正在实施很有用__getslice__默认jsys.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
于 2016-06-15T19:38:55.423 回答
0
于 2021-02-10T02:23:26.783 回答
0

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

现在回答实际问题:

切片有两个默认值

  1. 当 step 为 +ve 时的默认值

    0:TAIL:+ve 步

  2. step 为 -ve 时的默认值

    HEAD:-1:-ve 步骤

于 2021-01-30T17:51:01.583 回答