切片索引具有有用的默认值;省略的第一个索引默认为零,省略的第二个索引默认为要切片的字符串的大小。
>>> a = "hello"
>>> print(a[::-1])
olleh
正如教程所说,a[::-1]
应该等于a[0:5:-1]
但a[0:5:-1]
为空,如下所示:
>>> print(len(a[0:5:-1]))
0
问题不是explain-slice-notation的重复。那个问题是关于python中切片的一般用法。
答案 0 :(得分:21)
我认为文档可能对此有点误导,但如果省略则切片的可选参数与使用None
相同:
>>> a = "hello"
>>> a[::-1]
'olleh'
>>> a[None:None:-1]
'olleh'
你可以看到这两个切片与CPython字节码相同:
>>> import dis
>>> dis.dis('a[::-1]') # or dis.dis('a[None:None:-1]')
1 0 LOAD_NAME 0 (a)
3 LOAD_CONST 0 (None)
6 LOAD_CONST 0 (None)
9 LOAD_CONST 2 (-1)
12 BUILD_SLICE 3
15 BINARY_SUBSCR
16 RETURN_VALUE
对于否定的step
,None
的替换值为len(a) - 1
的{{1}}和start
的{{1}}:
-len(a) - 1
这可以帮助您想象它:
end
答案 1 :(得分:3)
所有这一切都是slice。你选。开始停止和步骤所以基本上你说它应该从头开始直到开始但向后(-1)。
如果你用-2做它会跳过字母:
>>> a[::-2]
'olh'
当你从第一个字母开始[0:5:-1]
时,直接回到5,因此它会停止。只有当您尝试[-1::-1]
时才会通过执行否定步骤1来正确地开始。
修改以回复评论
正如documentation所说的那样
省略的第二个索引默认为字符串的大小 切片。
假设我们str
有len(str) = 5
。当你对字符串进行切片并省略时,请忽略,第二个数字默认为被切片的字符串的长度,在本例中为5。
即str[1:] == str[1:5]
,str[2:] == str[2:5]
。句子指的是原始对象的长度,而不是新切片的对象。
此外,this answer很棒
答案 2 :(得分:3)
你对踩踏的行为感到困惑。要获得相同的结果,您可以做的是:
a[0:5][::-1]
'olleh'
事实上,步进想要“绕圈”。在你的情况下倒退,但是你通过拨打a[0:5:-1]
来限制它的移动。
答案 3 :(得分:2)
a[0:5:-1]
没有多大意义,因为当您使用此表示法时,索引意味着:a[start:end:step]
。当您使用负步时,您的结束值需要处于比起始值更“早”的位置。
答案 4 :(得分:1)
您会注意到第三个切片参数step
未在您引用的教程部分中显示。该特定片段采取积极步骤。
当您添加消极步骤的可能性时,行为实际上非常直观。空start
参数指的是序列中的任何一端,以step
值指示的方向逐步遍历整个序列。换句话说,如果你有一个正步骤,它指的是最低指数(计数),如果你有一个负步骤,它指的是最高指数(倒计时)。同样地,一个空的end
参数指的是在以适当的方向踩到之后最终会出现的序列中的任何一端。
答案 5 :(得分:0)
您所指出的文档对默认值完全不正确。但是,除了那个小错误外,它们是一致的。您可以在这里查看我所指的文档:https://docs.python.org/3/library/stdtypes.html#common-sequence-operations
从第i步到第j步的s切片被定义为 索引为x = i + n * k的项,使得0 <= n <(j-i)/ k。其他 换句话说,索引是i,i + k,i + 2 * k,i + 3 * k等,在j时停止 已达到(但不包括j)。
当您这样做:
>>> a = "hello"
>>> y = a[0:5:-1]
我们有i == 0
,j == 5
和k == -1
。因此,我们从x = i + n*k
到n
的{{1}}的索引0
处抓取项目。但是,请注意(j-i)/k
。没有(j-i)/k == (5-0)/-1 == -5
这样的n
,因此您得到了空字符串:
0 <= n < -5
>>> y
''
(这几乎总是我们想要的)几乎总是这样,当您对a[start:stop][::step]
之类的东西采取否定步骤时,您想要想要发生的事情是先进行子选择,然后才向后退x[start:stop:step]
(即我们通常想要step
。
更进一步,更令人困惑的是,
x[start:stop][::step]
如果x[start:stop:step] == x[start:stop][::step]
。例如:
step > 0
不幸的是,即使很想这么做,>>> x = list(range(10))
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x[2:6:2]
[2, 4]
>>> x[2:6][::2]
[2, 4]
>>> x[1:10][::3]
[1, 4, 7]
>>> x[1:10:3]
[1, 4, 7]
也不成立。
在被这几次烧掉之后,我意识到在执行step < 0
切片之后始终执行step子句 只是更安全。因此,我几乎总是从start:stop
开始,至少在进行原型设计或创建新模块时,首先要考虑正确性/可读性。这比执行单个切片的性能要差,但是如果性能是一个问题,那么您可以做的可读性较低:
y = x[start:stop][::step]
HTH。
答案 6 :(得分:0)
对于Python切片序列[start:stop:step] ,已得出以下规则:
#开始:停止:+步骤规则
#开始:停止:分步规则