4
>>>"helloworld"[::1]
'helloworld'

>>>"helloworld"[::-1]
'dlrowolleh'

根据语法str[start:end:step]。在这两种情况下,开始默认为 0。在第一种情况下,字符串从索引值 0 开始打印。但在第二种情况下,字符串从索引值 -1 开始打印。

我的问题是为什么在后一种情况下从 -1 打印字符串,为什么会这样?

4

7 回答 7

8

根据文档(强调添加):

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

这意味着如果切片步幅为正,则省略的切片开始是序列的开始,而省略的切片结束是序列的结尾。如果切片步幅为负,则相反。如果您填写以下两个值之一,您可以看到这一点:

>>> '0123456'[:3]
'012'
>>> '0123456'[:3:-1]
'654'
>>> '0123456'[3:]
'3456'
>>> '0123456'[3::-1]
'3210'

考虑这一点的一种方法是将序列可视化为一个循环,其中起点和终点是同一点。当您省略切片的一端时,您只是指定使用这个“两端点”作为端点,而不是从那里往哪个方向走。步幅标志告诉您要走哪条路,这决定了您是将“两端点”视为序列的开始还是结束。

于 2012-10-16T07:50:52.793 回答
2

扩展切片组件都默认为 None (相对于 0 和sys.maxint简单切片):

>>> class A:
...   def __getitem__(self, s):
...     return s
... 
>>> A()[::-1]
slice(None, None, -1)
>>> A()[:]
slice(0, 9223372036854775807, None)

因此,没有自动假定切片应该默认从零开始。

于 2012-10-16T07:48:35.217 回答
1

可视化这个

记住切片如何工作的最佳方法是将索引视为字符之间的指向,第一个字符的左边缘编号为 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'
于 2012-10-16T07:50:35.183 回答
0

在 python 中,字符串索引如下所示。

"H e l l o"
0 1 2 3 4
-4 -3 -2 -1 0

将使用的索引取决于您所取切片的方向。因为您给出的步骤是相反的方向,所以它使用下面的索引。但是,这在文档中没有明确说明。

编辑:

我实际上重新检查并有趣

str[::-1]
str[0::-1]
str[-1::-1]

所有返回相同的值。所以我在原始帖子中所说的似乎是错误的。它看起来更像是语言中的错误或特殊情况处理。

于 2012-10-16T07:44:57.073 回答
0

使用 step = 1,不出所料,您将获得原始字符串。

在 step = -1 的情况下,python 可能实现了一种特殊情况:颠倒顺序。

毕竟, slice [start:end], as[:]返回完整的 slice,这是预期的行为。所以将其视为两阶段操作:获取切片(在您的情况下为完整副本),应用步进(在您的情况下反向)。

于 2012-10-16T07:36:09.443 回答
0

您所看到的称为striding

>>> 'helloworld'[::1]

返回所有元素同时

>>> 'helloworld'[::2]
'hlool'

返回每个第二个元素。所以,现在试试:

>>> 'helloworld'[::-2]
'drwle'

这从最后返回每 2 个元素。因此,自然地,从末尾开始的所有元素都是反转的字符串:

>>> 'helloworld'[::-1]
'dlrowolleh'
于 2012-10-16T07:46:03.673 回答
0

-1如果在字符串反转时start 不是隐式的,那将毫无意义。-1如果您尝试使用显式索引,您将看到在用作步骤时起始索引必须位于结束索引的右侧:

>>> "helloworld"[0:-1:-1]
''
>>> "helloworld"[-1:0:-1]
'dlrowolle'

就像在正常方式切片时,范围包括起点而不包括终点,所以hat index0不是范围的一部分。这是(AFAIK)切片符号的限制,它不可能对整个字符串进行显式反转,因为这不起作用:

>>> "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]
于 2012-10-16T07:47:15.030 回答