从python.org教程
Slice indices have useful defaults; an omitted first index defaults to zero, an omitted second index defaults to the size of the string being sliced.
1 2 3
| >>> a ="hello"
>>> print(a[::-1])
olleh |
应该说,作为一a[0:5:-1]equals a[::-1]教程
但a[0:5:-1]is empty为如下:
1 2
| >>> print(len(a[0:5:-1]))
0 |
这样的问题是没有解释的重复(多层的符号。这是一个总在Python中使用切片。
- @Jean-Fran@35231;Oisfabre>
- The docs don't mention the case of reverse iteration,yes.Good point.
- 如何是EDOCX1的英文
- 这个工作-EDOCX1
- @Jean-Fran@35;231;oisfabre not sure this is a dupe.This question is really about the default values for the omitted slice indices in the cases of a negative step.I can't find i t documented anywhere,but really,as the tutorial states,"Slice indices have useful default".
- @Juanpa.arrivilaga this dupe question is good(i upvoted),and the most upvoted answer of the"original"question doesn't answer,but the other one does in a way.我从来没有因为每一次我被指责我有一个坏的经验。I'll let others do it if they want(you can vote!)
- @Jean-Fran@35231;Oisfabre whops!我不认为我会立即采取行动嗯
- Explain Slice notation的可能重复
- @Juanpa.arrivilaga with great power comes great responsibility:you just found out that Python gold badge can close/REOPEN singlehandly:
- I'd personally call this language inconsistency since in the same line of reasoning EDOCX1 original 2 works just as intuition would suggest.
我认为文档在这方面可能有点误导性,但是如果省略切片的可选参数与使用None相同:
1 2 3 4 5
| >>> a ="hello"
>>> a[::-1]
'olleh'
>>> a[None:None:-1]
'olleh' |
您可以看到上面的两个切片与cpython字节码完全相同:
1 2 3 4 5 6 7 8 9
| >>> 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代表start,-len(a) - 1代表end:
1 2 3 4 5 6
| >>> a[len(a)-1:-len(a)-1:-1]
'olleh'
>>> a[4:-6:-1]
'olleh'
>>> a[-1:-6:-1]
'olleh' |
这可能有助于您将其可视化:
1 2 3
| h e l l o
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1 |
。
- 你能给我看一些关于the substituted values for None are len(a) - 1 for the start and -len(a) - 1 for the end的推荐信吗?
- @亚历克斯:"当k为负时,如果i和j较大,则将它们减为len(s)-1。如果I或J被省略或没有,它们将成为"端"值(端取决于k的符号),见第5点。docs.python.org/3/library/…
- @亚历克斯还看到了这个相关的SO问题:stackoverflow.com/questions/12521798/…
你对脚步的行为感到困惑。要得到相同的结果,您可以做的是:
号
实际上,在你的例子中,stepping想要向后"循环",但是你通过调用a[0:5:-1]来限制它的移动。
- 我不同意这个解释,hello'[0:5:1]会返回hello,那么-1为什么要对''进行评估?
- 因为踩一点都不切,只踩几步。
- 不确定你的意思,我个人认为这是语言不一致。
它所做的就是切片。你挑吧。开始,停止,走,所以基本上你是说,它应该从一开始就开始,直到开始,但是向后走(-1)。
如果使用-2,它将跳过字母:
当你做[0:5:-1]时,你的E从第一个字母开始,直接回到5,这样它就会停止。只有当你尝试了EDOCX1[1]时,它才能正确地通过执行负1的步骤开始。
编辑以答复评论
正如文件所指出的那样
an omitted second index defaults to the size of the string being
sliced.
号
假设我们有str和len(str) = 5。当您对字符串进行切片并省略时,去掉第二个数字,它默认为要切片的字符串的长度,在本例中是-5。即str[1:] == str[1:5]、str[2:] == str[2:5]。句子指的是原始对象的长度,而不是新切片对象的长度。
而且,这个答案很好
- 我相信OP知道a[::-1]的作用。
- 本教程说,"省略的[::-1]的第二个索引应该是字符串大小",因此[::-1]等于[:5:-1]。你为什么说"从开始到开始"?我误解了吗?
- @亚历克斯,你能告诉我确切的位置吗?
- @isaacdj tutorial link docs.python.org/2/tutorial/introduction.html如下:Slice indices have useful defaults; an omitted first index defaults to zero, an omitted second index defaults to the size of the string being sliced.。
- @亚历克斯更新了答案
a[0:5:-1]没有多大意义,因为当使用这个符号时,指数的意思是:a[start:end:step]。当您使用负阶跃时,您的最终值需要处于比初始值"更早"的位置。
您会注意到第三个slice参数step没有在您引用的教程部分中出现。这个特定的片段假定是一个积极的步骤。
当你加入消极步骤的可能性时,行为实际上是非常直观的。一个空的start参数指的是序列的任何一端,即按照step值指示的方向,从该端开始逐步执行整个序列。换句话说,如果你有一个积极的步骤,它指的是最低的索引(向上计数),如果你有一个消极的步骤,它指的是最高的索引(向下计数)。同样,一个空的end参数指的是序列的任何一端,在沿着适当的方向通过之后,序列的任何一端都会结束。
对于序列[start:stop:step]的python切片,派生了以下规则:
开始:停止=开始:停止:1
开始:停止:(+或-)步骤-当遍历序列中的n个项目时。然而,(-)表示反向遍历
记住,最后一项的顺序位置是-1,而之前一项的顺序是-2,依此类推。
#开始:停止:+步骤规则
始终向前移动
始终从序列的开始作为其积极步骤(前进)
从请求的位置开始,在请求的位置停止,但不包括项目停止位置
默认开始:如果未提供开始,则从0开始
默认停止:如果不提供停止,则表示直到序列结束,包括最后一个值
如果停止位置的项不可访问(项超出序列遍历的结尾),则slice不返回任何内容。
#开始:停止:步骤规则
始终反向移动
如果提供了起始位置,则从该位置开始,但反向横移(向后退一步)
如果提供了停止,则停止在那里遍历,但不包括此
默认开始:如果没有提供开始位置,则开始位置是序列的最后一个位置(因为反向遍历)
默认停止:如果不提供停止,则它是列表的开始(位置0)
如果停止位置的项不可访问(项超出序列遍历的结尾),则slice不返回任何内容。
正如您所指出的,文档对于默认值是不正确的。但是,除了那个小错误,它们是一致的。您可以在这里查看我引用的文档:https://docs.python.org/3/library/stdtypes.html公共序列操作
请注意,根据文档,行为是绝对正确的:
The slice of s from i to j with step k is defined as the sequence of
items with index x = i + n*k such that 0 <= n < (j-i)/k. In other
words, the indices are i, i+k, i+2*k, i+3*k and so on, stopping when j
is reached (but never including j).
号
当你这样做的时候:
1 2
| >>> a ="hello"
>>> y = a[0:5:-1] |
我们有i == 0、j == 5和k == -1。因此,我们在指数x = i + n*k上为n抓取项目,从0开始,到(j-i)/k。然而,观察(j-i)/k == (5-0)/-1 == -5。没有n这样的0 <= n < -5所以得到空字符串:
号当有疑问时(这几乎总是我们想要的)做a[start:stop][::step]
几乎所有的情况都是这样的,当你向像x[start:stop:step]这样的事情迈出消极的一步时,你希望发生的事情是先进行子选择,然后再通过step向后(即我们通常希望x[start:stop][::step])。
此外,更令人困惑的是,事实上
1
| x[start:stop:step] == x[start:stop][::step] |
如果是step > 0。例如:
1 2 3 4 5 6 7 8 9 10 11
| >>> 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时,这并不适用,尽管它很容易让人认为应该这样做。
经过几次这样的处理,我意识到在执行start:stop切片之后总是执行step子句比较安全。因此,我几乎总是从y = x[start:stop][::step]开始,至少在原型设计或创建一个新模块时,正确性/可读性是首要问题。这比执行单个切片的性能差,但是如果性能是一个问题,那么您可以执行可读性差的操作:
1
| y = x[start:stop:step] if step > 0 else x[stop:start:step] |
Hth.