为什么使用[-1:-1:-1]不能反转字符串?

3
也许有人可以解释为什么一个用于反转字符串的切片操作无法正常工作。我一定是对切片操作有所误解。基本操作:s[start:end:step]。
给定:
s='abcd'

我可以使用默认值来反转这个字符串。

s[::-1]

或者
s[-1::-1]

那些都很好,但为什么不呢?
s[-1:-1:-1]

请帮我将整个字符串反转?字符串应该以最后一个字符(-1)开始,步长为-1。它应该一直运行到-1之前,即索引0。但是我得到了“”。

for i in xrange(3, -2, -1):
    print 's[-1:%d:-1] => ' %i,
    print s[-1:i:-1]

输出:

s[-1:3:-1] =>     # didn't expect any output
s[-1:2:-1] =>  d
s[-1:1:-1] =>  dc
s[-1:0:-1] =>  dcb
s[-1:-1:-1] =>    # shouldn't this be 'dcba'?

我在这里错过了什么?

(我确实看到很多关于反转字符串的帖子,但如果这个特定项目已经有解释,那我可能错过了)


2
如果你的切片起始和结束索引相同,它怎么可能不是空的呢? - FatalError
就像@FatalError所说的那样。顺便说一下,“-1之前的一个”不会是索引0,而应该是-2。从算术上讲,0是在-1之后的第一个数。 - smci
是的,你可以构造一个字符串切片,它试图从0向下计数。但它的行为很奇怪:s[2:-2:-1] 奇怪地为空,但 s[-2:2:-1] 似乎可以工作,尽管乍一看不应该这样。 - smci
6个回答

6
s[-1:-1:-1]

由于相同的原因,它无法正常工作。
s[0:0]

当你进行切片操作时,你是指的两个元素之间的空间而不是这些元素的位置。因此,你正在请求-1和-1之间的空间,这是''。

不会给你“abcd”。


谢谢。我太专注于索引值本身,而不是“切片”的语义,即它们之间的空间。非常有帮助。 - Levon

3
在这个上下文中,负索引和非负索引是两个不同的类别:
  • 非负索引从开头开始;
  • 负索引从末尾开始。
在我看来,切片被定义为后者永远不会溢出到前者,就像你在说“它应该一直运行到-1之前,即索引0”时期望的那样,这似乎非常合乎逻辑。

3

In

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

startend 都是 -1,所以它们是相同的。一个切片会在每次增加 step 的同时,从数组中的 startend 取出每个元素。如果已经达到了 end,则切片结束... 因此返回 ''

尝试:

>>> s[1:1:1]
>>> ''

这可能会使它更加易懂,因为它几乎是相同的事情,但是积极的。

谢谢,你是对的,将所有正索引值一起查看确实让人清楚明白。由于我的其他示例(在循环中)按我预期工作,所以我错误地假设我的结论也是正确的。 - Levon

1
你完全没有理解切片的重点
如果使用切片操作符,它会像这样:[start:end:stride] 如果步长为负数,则起始点一定要大于结束点,因为这样才能从高到低移动。你提供的所有不成功的示例都违反了这一点。
你应该一定要阅读Extended Slicing

我有,但是我可能会从复习中受益 - 谢谢。 - Levon

1

你不能指望-1同时表示字符串中最后一项和第一个项之前的"项"。这是不一致的。

也许你认为Python会将字符串视为循环,并认为-1同时表示0之前的"项"和字符串的最后一项。但事实并非如此。例如,如果真是这样,那么下面的情况应该成立:

'abcd'[-2:-1:-1] == 'cbad'

但它并没有。结果只是一个空字符串。
>>> 'abcd'[-2:-1:-1] 
''

在字符串切片中,负数索引的正确解释是从字符串末尾开始的反向索引,而不是从0开始的循环索引。
进一步思考,可以考虑以下内容:
a = 'abcd'
a[-1:-(len(a) + 0):-1] == 'dcb'
a[-1:-(len(a) + 1):-1] == 'dcba'
a[-1:-(len(a) + 2):-1] == 'dcba'

1

这有点不幸,是吧?这里有一个尴尬的解决方法。

for i in range(3, -2, -1):
    j = i if i != -1 else None
    print 's[-1:%s:-1] => ' % str(j),
    print s[-1:j:-1]

s[-1:3:-1] =>  
s[-1:2:-1] =>  d
s[-1:1:-1] =>  dc
s[-1:0:-1] =>  dcb
s[-1:None:-1] =>  dcba

这是同样事情的一个变化。我不确定它是否更加自然。

for i in range(3, -1, -1) + [None]:
    print 's[-1:%s:-1] => ' % str(i),
    print s[-1:i:-1]

s[-1:3:-1] =>  
s[-1:2:-1] =>  d
s[-1:1:-1] =>  dc
s[-1:0:-1] =>  dcb
s[-1:None:-1] =>  dcba

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接