Python :反向迭代时包括最后一个元素(其中 i=0)

Python : include last element (where i=0) when iterating in reverse

我有一个字符串 string = 'cbAfeDihGlkJonMrqPutS',我想遍历它以产生 'AbcDefGhiJklMnoPqrStu'.

我正在使用以下 for 循环来实现 'DefGhiJklMnoPqrStu,但是缺少预期的 Abc

for i in (range(0, len(string), 3)):
    print(string[i+2 : i-1 : -1], end='')

这似乎是一个问题,因为我的结束元素 : i-1 : 中的 -1,但是我想知道为什么反向迭代(步长为 -1)并使用:i-1: 捕获第一个元素(其中 i=0)与向前迭代并使用 : i+1 : 捕获最后一个元素的工作方式不同。

我能够通过

实现我想要的解决方案
for i in (range(0, len(string), 3)):
    print(string[i:i+3:1][::-1], end='')

但是向前迭代和向后打印似乎是一种笨拙的方法。必须添加 [::-1] 似乎是一个多余的步骤,如果 [i+2 : i-1 : -1] 有效。

除了 [i:i+3:1][::-1] 之外,还有更简洁的方法吗?

最优雅的方法可能是使用 ''.join() 和理解将您已经想出的循环压缩成一行。

string = 'cbAfeDihGlkJonMrqPutS'
print(''.join(string[i:i+3][::-1] for i in range(0, len(string), 3)))
# AbcDefGhiJklMnoPqrStu

您认为您可以像 string[i+2:i-1:-1] 这样的操作去掉多余的 [::-1],但正如您所观察到的,这会截断字符串中的第一个字符.这是切片语法的一个怪癖,切片的 end 边界是 exclusive 而不是 inclusive,但同时索引 -1 指的是结尾的字符串而不是 'the character before the beginning'(这将超出范围,比如说 Java,但我们不会有这个问题)。据我所知,没有办法解决这个问题。

您也可以尝试使用 reversed() 而不是 [::-1],但我不认为这会使它变得更简单或更快:

print(''.join(c for i in range(0, len(string), 3) for c in reversed(string[i:i+3])))

编辑:正如@don't talk just code pointed out in a comment,实际上可以规避这个问题,因为将None作为第二个切片的参数将使切片继续到列表的任何一端是合适的(直到这个评论我不知道这一点)。考虑到这一点,我们确实可以只用一片来完成这件事:

print(''.join(string[i+2:i-1 if i else None:-1] for i in range(0, len(string), 3)))
# AbcDefGhiJklMnoPqrStu

它有点不雅,但它似乎有效,并且比上面的更符合您的要求。