Python字符串切片,如果包含字符串结尾,则为特例?

Python字符串切片,如果包含字符串结尾,则为特例?,python,slice,Python,Slice,我是Python新手,我发现切片行为有些混乱 如果我这样做 test = 'abcdefgh' for i in range(7): print test[-(8-i):-(6-i)] print i 最后一次迭代将出现错误。因为切片[start:end]不包括end,所以在我看来,如果最后一个字符在我想要的范围内,我需要用一个特例来处理这样的切片 我遗漏了什么吗?这里的问题是-0就是0,所以您试图获取字符串的第一个字符 对于i=6的情况,得到 test[-2:0] = ''

我是Python新手,我发现切片行为有些混乱

如果我这样做

test = 'abcdefgh'

for i in range(7):
    print test[-(8-i):-(6-i)]
    print i
最后一次迭代将出现错误。因为切片[start:end]不包括end,所以在我看来,如果最后一个字符在我想要的范围内,我需要用一个特例来处理这样的切片


我遗漏了什么吗?

这里的问题是-0就是0,所以您试图获取字符串的第一个字符

对于i=6的情况,得到

test[-2:0] = ''
更好的处理方法是向前看

for i in range(len(test)-1):
     print test[i:i+2]
对于从结尾到工作的索引,正确的语法将省略0

test[-2:] = 'gh'

你不能从-1开始,然后转到+1-1是结束,1是第二个基金项目。你能行

for i in range(7):
   ....:         print test[i:(2+i)]
   ....:     
ab
bc
cd
de
ef
fg
gh

如果再添加几张照片,您可以看到发生了什么:

测试='abcdefgh'

for i in range(7):
    print -(8-i), -(6-i)
    print test[-(8-i):-(6-i)]
    print i
产出:

-8 -6
ab
0
-7 -5
bc
1
-6 -4
cd
2
-5 -3
de
3
-4 -2
ef
4
-3 -1
fg
5
-2 0
所有的范围都是负数,直到最后一个范围为0

或None
添加到结束范围将避免
0
,并表现为一开始没有通过:

for i in range(7):
    print test[-(8-i):(-(6-i) or None)]
    print i
哪些产出:

ab
0
bc
1
cd
2
de
3
ef
4
fg
5
gh
6

按照
运算符的工作方式,如果第一个参数是“falsish”,则使用第二个参数,在这种情况下

这确实是切片语义的不幸结果

问题在于,要表示“从末尾开始计数”,您需要传递一个负数,因此您不能询问“从末尾开始计数0”,因为
-0==0
不是负数

要从末尾开始计算0个字符,您需要使用
if
或其他条件欺骗对问题进行特殊处理,因为传递
0
意味着“从开始算起0个元素”

要让它在这些情况下工作,语义必须是
-4
意味着从末尾数3(因此给-1留出空间表示“从末尾数0”),但这会违反直觉

能够说
x[-n:]
表示字符串的最后一个
n
字符是一个更好的折衷办法,即使这对
n==0
不起作用,在这里可以得到完整字符串,而不是空字符串。

在Python教程()中,切片表示法定义为两个由冒号分隔的索引

在示例的最后一次迭代中,切片表示法是[-2:0]-2是字符串倒数第二个字符的索引,0是字符串中第一个字母的索引。从第二个到最后一个字符到第一个字符进行切片是没有意义的

如果要从第二个到最后一个字符到最后一个字符,只需删除第二个索引:[-2:]。也就是说,从倒数第二个字符开始,一直到最后一个字符。或者明确地说[-2:len(test)]

对于本例,我建议如下所示:

test = 'abcdefgh'
for i in range(7):
    start = -(8-i)
    end = -(6-i)
    # test your end condition
    if end == 0:
        end = None
    print test[start:end]
    print i

请注意,
“a”[0:100000]==“a”
。当对超出范围的索引使用切片时,不会得到
索引器
。超出范围的索引或者替换为结束/开始,或者在其他情况下,结果是空字符串。是的。因此,对于一致性,我更愿意[-2:0]与[-2:end]相同,而不是只给出一个空片段。实际上,这会降低一致性。因为:为什么
[-2:1]
[-2:0]
工作时返回空字符串?一件事是如果省略
stop
参数,另一件事是如果提供显式索引。我不介意[-2:2]是否给出字符串的最后两个和前两个字符。我突然想到python的切片提供了一个非常强的不变量。给定一个字符串
s
,它总是认为:
s
中的
s[x:y]是
True
,无论
x
y
是什么,如果省略它们;换句话说,
s[x:y]
始终是
s
的子字符串(如果省略该步骤)。包括您建议的更改将打破此不变。我相信这就是为什么他们不想在这种情况下含蓄地改变步骤的原因
s[x:y]
应始终返回
s
的子字符串,而不是
s
的子字符串或
s
的逆字符串,具体取决于索引。是的,我明白了。我只是觉得很奇怪,他们给你提供了“从结尾开始索引”——速记,但使它对最后一个字符不起作用。这是因为当你在该位置插入0时,你不再从结尾开始索引。对于这种情况,正确的“从末尾索引”应该是test[-2:]我知道。对我来说,允许类似[-2:0]的东西(意思与[-2:]相同)来简化这一过程是有道理的。“或无”-解决方案相当简短且切中要害,但我不明白为什么不允许0作为两个方向的索引。因为如果0同时表示两个方向,则0将是不明确的,因此不可用。如果您考虑为这种语言实现一个解析器,它很容易根据数字是否为负数来区分从末尾索引和按位置索引。我还认为更为传统/可读的方式是我上面提到的方式。老实说,我花了一分钟的时间来思考你的陈述所期望的结果是什么。通常,我会使用你上面提到的方法。我只是在尝试这种“新奇”的速记时遇到了这个问题。刚刚意识到在Python'a'*5=='aaaaa'中,我有点希望切片也是“神奇的”,允许[-2:5]之类的东西。哦,好吧,我想我会习惯的。好吧,酷,这是一个相当直接的方式使这项工作我承认这有点尴尬,但它避免了需要为它做一个特殊的案例。负切片很好,直到你遇到这样的事情。任何其他解决方法都需要一个
if..else
语句,这会让我觉得很糟糕,直到我意识到默认参数
None
可以很容易地插入