来自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'
切片永远不会包含切片中第二个索引的值。我可以看到这样做的一致性。
所以我认为我开始理解切片在各种排列中的行为。但是,我觉得第二个索引有点特殊,并且负步骤的第二个索引的默认值实际上不能用数字来定义。
任何人都可以简明地定义可以解释所提供示例的默认切片索引吗?文档将是一个巨大的优势。
答案 0 :(得分:8)
实际上没有任何默认值;省略的值是专门处理的。
但是,在每种情况下,省略的值恰好以与None完全相同的方式处理。这意味着,除非您正在攻击解释器(或使用parser
,ast
等模块),否则您可以假装默认值为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
。换句话说,索引是i
,i+k
,i+2*k
,i+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.maxsize
(https://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 结束。
现在回答实际问题:
切片有两个默认值
step 为 +ve 时的默认值
0:TAIL:+ve 步
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
是负数,所以我们将 left 从 i
移到 j
。由于 i
是空的,我们从 右 边缘开始,选择直到但不包括索引 3 处的元素的所有内容。
>>> s[0:3:-1]
''
这里,k
是负数,所以我们将 left 从 i
移到 j
。由于索引 3 不在索引 0 的左侧,因此没有选择任何元素,我们返回空字符串。