>>>"helloworld"[::1]
'helloworld'
>>>"helloworld"[::-1]
'dlrowolleh'
根据语法
str[start:end:step]
,默认情况下两种情况下的起始位置都是0。在第一种情况下,字符串从索引值0开始打印。但是在第二种情况下,字符串从索引值-1开始打印。我的问题是为什么后一种情况下字符串从-1开始打印,为什么会这样?>>> '0123456'[:3]
'012'
>>> '0123456'[:3:-1]
'654'
>>> '0123456'[3:]
'3456'
>>> '0123456'[3::-1]
'3210'
扩展切片组件默认全部为None(与简单切片的0和sys.maxint
相对):
>>> class A:
... def __getitem__(self, s):
... return s
...
>>> A()[::-1]
slice(None, None, -1)
>>> A()[:]
slice(0, 9223372036854775807, None)
形象化一下
记住切片的最好方法是将索引视为指向字符之间的位置,其中第一个字符的左边缘编号为0。然后,n个字符的字符串的最后一个字符的右边缘具有索引n,例如:
+---+---+---+---+---+
| H | e | l | l | o |
+---+---+---+---+---+
0 1 2 3 4 5
-5 -4 -3 -2 -1
索引可能是负数,以从右侧开始计数。但请注意,-0实际上与0相同,因此不会从右侧计数!
In [105]: "helloworld"[-0]
Out[105]: 'h'
In [106]: "helloworld"[0]
Out[106]: 'h'
即为什么反向索引从-1开始
In [107]: "helloworld"[-1]
Out[107]: 'd'
要获取字符串的倒数第二个索引,即[-2]
,也就是倒数第二个字符,需要使用负步长来到达下一个索引。
In [108]: "helloworld"[-1 + -1]
Out[108]: 'l'
"H e l l o"
0 1 2 3 4
-4 -3 -2 -1 0
将要使用的索引取决于您正在获取的切片方向。因为您提供的步长是相反方向,它使用下面的索引。然而,在文档中并没有明确说明这一点。
编辑:
我实际上重新检查了,有趣的是
str[::-1]
str[0::-1]
str[-1::-1]
所有返回相同的值。因此,我在原帖中所说的似乎是错误的。它看起来更像是语言中的一个错误或特殊情况处理。
>>> 'helloworld'[::1]
>>> 'helloworld'[::2]
'hlool'
返回每2个元素。现在尝试:
>>> 'helloworld'[::-2]
'drwle'
这将返回从末尾开始的每2个元素。因此,自然而然地,从末尾开始的所有元素就是反转的字符串:
>>> 'helloworld'[::-1]
'dlrowolleh'
如果反转字符串时起始位置不是隐式的-1
,那么就没有意义。如果您尝试使用显式索引,您会发现当使用-1
作为步长时,起始索引必须在结束索引的右侧:
>>> "helloworld"[0:-1:-1]
''
>>> "helloworld"[-1:0:-1]
'dlrowolle'
正如普通切片时一样,范围包括起始点但不包括结束点,因此索引0
处的h
不是范围的一部分。据我所知,这是切片符号的一个限制,因为无法执行整个字符串的明确反转,因为以下操作无法实现:
>>> "helloworld"[-1:-1:-1]
''
因此,一个切片和反转函数必须针对这种情况进行特殊处理:
def slice_and_reverse(s, a, b):
"Return a slice of s from a to but not including b, reversed."
if a == 0:
return s[b - 1::-1]
else:
return s[b - 1:a - 1:-1]
当步长为1时,您将获得原始字符串,这并不奇怪。
当步长为-1时,Python可能会实现一个特殊情况:反转顺序。
毕竟,切片[start:end]
,如[:]
返回完整的切片,这是预期的行为。因此,将其视为两个阶段的操作:获取切片(在您的情况下是完全复制),然后应用步幅(在您的情况下是反向)。