鱼C论坛

 找回密码
 立即注册
查看: 2536|回复: 13

再问列表切片的负数步长

[复制链接]
发表于 2023-4-2 18:46:58 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
>>list = [1, 2, 3, 4, 5 , 6]
>>list[::-3]
>>[6,3]
没看懂返回值结果是怎么来的呢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-4-2 18:55:21 | 显示全部楼层
这段代码的意思是先创建了一个列表 list,包括 1 到 6 的整数。然后使用列表切片的方式,从列表末尾开始每隔 3 个元素取一个元素,最后返回这些被选中的元素组成的新列表。具体来说:

[::-3] 表示取整个列表的逆序,步长为 3。
取到的第一个元素是 6,因为它是距离列表末尾最近的且索引可以被 3 整除的元素(即列表的倒数第一个元素)。
然后跳过两个元素,再次找到一个满足要求的元素 3(即列表的倒数第四个元素)。
再次跳过两个元素,没有更多满足要求的元素了,于是返回由 6 和 3 组成的新列表 [6, 3]。
需要注意的是,在切片时如果不指定起始索引和终止索引,则默认从列表的开头到结尾。而如果步长是负数,则表示从列表的结尾开始取元素。所以 [::-3] 可以看作是 len(list)-1::-3 的缩写形式,其中 len(list)-1 对应的是列表的最后一个元素的索引。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-2 18:57:11 | 显示全部楼层
这是 Python 中列表(list)的一种切片方式,表示从列表的结尾到开头,每隔两个元素取一个元素,也就是取列表中索引值为 -1、-4 等位置上的元素。其中第一个冒号前面的空位表示起始位置,默认是 -1,第二个冒号后面的空位表示结束位置,默认是 -len(list)-1,而中间的数字 -3 表示步长,即每次跳过的元素个数。

因此,对于给定的 `list = [1, 2, 3, 4, 5 , 6]`,`list[::-3]` 返回的是从最后一个元素开始,每隔两个元素取一个元素,直到遍历到列表的开头或者只剩下一个元素时停止。所以返回的结果是 `[6,3]`,即列表中倒数第一个元素和倒数第四个元素构成的新列表。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-2 18:58:36 | 显示全部楼层
当你在Python中使用列表的切片(slice)操作时,可以指定3个参数:起始索引、结束索引和步长。在你给出的例子中,你使用了一个负数作为步长:

list[::-3] 表示你希望从列表的末尾开始,按照步长3的方式向列表的开头方向遍历。[::-3] 的含义如下:

起始索引:默认为空,表示从列表的末尾开始。
结束索引:默认为空,表示遍历至列表的开头。
步长:-3,表示每次向前(左边)跳过2个元素(间隔为3)。
现在,让我们详细看一下列表的每个元素:

索引: 0  1  2  3  4  5
元素: 1  2  3  4  5  6


根据切片操作,我们从末尾开始(索引5,元素6),然后以步长-3向前遍历。第一次遍历,我们取到索引5的元素6。然后再向前跳过2个元素(索引3和4),取到索引2的元素3。此时已经到达列表的开头,所以切片操作完成。

因此,结果是[6, 3]。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-2 19:17:58 | 显示全部楼层
liuhongrun2022 发表于 2023-4-2 18:55
这段代码的意思是先创建了一个列表 list,包括 1 到 6 的整数。然后使用列表切片的方式,从列表末尾开始每 ...

还需要可以被 3 整除?

那如果刚好对应的两个元素都不能被3整数怎么办?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-2 19:27:16 | 显示全部楼层
lzb1001 发表于 2023-4-2 19:17
还需要可以被 3 整除?

那如果刚好对应的两个元素都不能被3整数怎么办?

非常抱歉,我的回答有误,不必要求选取的元素下标必须能被 3 整除。

在这段代码中,切片 [::-3] 取反后每隔三个元素取一个元素。因此,在列表 list 中,第一个选定的元素是最后一个元素 6,然后需要跳过两个元素,然后查询下一个符合条件的元素,发现是倒数第四个元素 3,再次跳过两个元素发现没有下一个符合条件的元素了。所以最终选定的元素是 6 和 3,组成新列表 [6, 3]。

如果在这个过程中有某一步没有找到符合条件的元素,则会直接停止搜索,返回当前已经选定的元素组成的新列表。也就是说,如果在这个例子中没有找到一个元素的下标既是 3 的倍数又是列表长度的倍数,则它们之间的元素会被忽略掉。

感谢您提出问题,希望这次解释更加清晰明了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-2 19:41:19 | 显示全部楼层
本帖最后由 lzb1001 于 2023-4-3 01:12 编辑

按我的理解:

ls[::-3]不是应该等于ls[0:7:-3](前正后反),或者ls[-1:-7:3](前反后正)

然而:

ls[0:7:-3](前正后反),或者ls[-1:-7:3](前反后正)返回的都是空列表[ ]

ls[::-3]实际真正应等于ls[-1:-7:-3]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-2 19:45:58 | 显示全部楼层
lzb1001 发表于 2023-4-2 19:41
按我的理解:

ls[::-3]不是应该等于ls[1:7:-3](前正后反),或者ls[-1:-7:3](前反后正)

我明白你的困惑。但实际上,当你使用负的步长时,起始索引和结束索引的默认值是不同的。这就是为什么 ls[::-3] 能得到 [6, 3] 的结果。

当你使用负数作为步长时,起始索引默认值是列表的最后一个元素(即 -1),而结束索引默认值是列表的开始(实际上是空,因为不包括结束索引)。因此,ls[::-3] 实际上等于 ls[-1:None:-3]。

让我们再看一下切片操作的步骤:

索引:  0  1  2  3  4  5
元素:  1  2  3  4  5  6
负索引:-6 -5 -4 -3 -2 -1

现在,我们从末尾开始(索引 -1,元素 6),然后以步长 -3 向前遍历。第一次遍历,我们取到索引 -1 的元素 6。然后再向前跳过 2 个元素(索引 -3 和 -2),取到索引 -4 的元素 3。此时已经到达列表的开头,所以切片操作完成。

因此,结果是 [6, 3]。

对于你提到的其他两种写法:

ls[1:7:-3]:由于步长是负数,起始索引(1)比结束索引(7)大,所以返回空列表。
ls[-1:-7:3]:由于步长是正数,起始索引(-1)比结束索引(-7)小,所以返回空列表。

这就解释了为什么 ls[::-3] 的结果是 [6, 3]。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-2 20:02:11 | 显示全部楼层
isdkz 发表于 2023-4-2 19:45
我明白你的困惑。但实际上,当你使用负的步长时,起始索引和结束索引的默认值是不同的。这就是为什么 ls[ ...


容我消化和理解一下。

不过这也纠正一个我之前的错误认识:

小甲鱼在教材中举例:

>>list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>list1[::-1]
>>[9, 8, 7, 6, 5, 4, 3, 2, 1]

因为教材前面提到:
>>list1[::]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

[0:9]可以简写成[::],

所以我之前一直以为list1[::-1] = [0:9:-1]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-2 20:17:56 | 显示全部楼层
>>list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]

要想获得[9, 8, 7, 6, 5, 4, 3, 2, 1]:

>>> list1[::-1] # 表达形式1
[9, 8, 7, 6, 5, 4, 3, 2, 1]

>>> list1[-1::-1] # 表达形式2
[9, 8, 7, 6, 5, 4, 3, 2, 1]

>>> list1[::-10:-1] # 不可!!!
SyntaxError: invalid syntax


----------------

要想获得[1, 2, 3, 4, 5, 6, 7, 8, 9]:

>>> list1[:] # 表达形式1
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> list1[::] # 表达形式2
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> list1[0:] # 表达形式3
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> list1[0::] # 表达形式4
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> list1[:10] # 表达形式5
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> list1[::10] # 不可!!!
[1]


>>> list1[0:10] # 表达形式6
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> list1[0::10] # 不可!!!
[1]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-3 01:02:05 | 显示全部楼层
本帖最后由 lzb1001 于 2023-4-3 01:05 编辑

按2楼大神的意思是:list[len(list)-1:1:-3]

按3楼大神的意思是: list[-1:-len(list)-1:-3]

都可以获得[6, 3]的返回结果

如果按我之前的错误理解:

>>> list[1:len(list)-1:-3]

>>> list[-len(list)-1:-1:-3]

返回的都是空列表[]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-3 01:11:26 | 显示全部楼层
liuhongrun2022 发表于 2023-4-2 19:27
非常抱歉,我的回答有误,不必要求选取的元素下标必须能被 3 整除。

在这段代码中,切片 [::-3] 取反 ...

……也就是说,如果在这个例子中没有找到一个元素的下标既是 3 的倍数又是列表长度的倍数,则它们之间的元素会被忽略掉。

这句话确认没有错误?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-3 01:21:12 | 显示全部楼层
本帖最后由 lzb1001 于 2023-4-3 01:37 编辑
isdkz 发表于 2023-4-2 19:45
我明白你的困惑。但实际上,当你使用负的步长时,起始索引和结束索引的默认值是不同的。这就是为什么 ls[ ...


1、也可以按2楼大神的意思list[len(list)-1:1:-3],同样也可以得到[6, 3]相同的返回结果呢


2、我看不太明白红色字体:

ls[1:7:-3]:由于步长是负数,起始索引(1)比结束索引(7)大,所以返回空列表。 ----为什么1比7大?不是7大于1吗?
ls[-1:-7:3]:由于步长是正数,起始索引(-1)比结束索引(-7)小,所以返回空列表。----为什么-1比-7小?不是-7小于-1吗?

就是说:

如果步长是负数,起始索引必须比结束索引小,否则返回空列表。
如果步长是正数,起始索引必须比结束索引大,否则返回空列表。

大小是怎么比较?有点搞糊涂了


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-3 01:27:01 | 显示全部楼层
lzb1001 发表于 2023-4-3 01:21
按2楼大神的意思list[len(list)-1:1:-3]也可以得到[6, 3]相同的返回结果呢

他的中间是没有 1 的,你这个不能等同于 list[::-3],因为他的结束索引不包含在内的

这里只是巧合结果一样而已,如果元素的个数刚好最后能取到第一个元素,你这个写法是不会包含第一个元素的

>>> list = [1, 2, 3, 4, 5 , 6, 7]
>>> list[::-3]
[7, 4, 1]
>>> list[len(list)-1::-3]
[7, 4, 1]
>>> list[len(list)-1:None:-3]
[7, 4, 1]

>>> list[len(list)-1:1:-3]
[7, 4]

>>>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-30 02:20

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表