a
[0、1、2、3、4、5、6、7、8、9]
为了便于总结,我们试着将切片的应用分成小类型。
4.1 .如果切片式只有一对冒号
【提示】在这种情况下,步长值step为1,因此隐含假设切片方向遵循“从左到右”切割的原则。
a
[0、1、2、3、4、5、6、7、8、9]
4.1.1最简单的情况
a[2:6]
[ 2,3,4,5 ]
a[2:9]
[2、3、4、5、6、7、8]
【提示】在这两个示例中,由于遵循“左闭右开”原则,因此会从最终切片的结果集中删除最后一个下标元素。
4.1.2切片的截止位置“超界”
根据上述切片规则7的说明,在切片操作时索引没有真正的“越界”问题。 请结合切片规则7查看以下示例。
a[2:10]
[2、3、4、5、6、7、8、9]
【分析】根据“左闭右开”原则,切片结果集包含从a[2]、a [3]……到a[2]的8个元素。
a[2:20]
[2、3、4、5、6、7、8、9]
【解析】根据切片规则7,a[2:20]等价于a[2:20]。 (10=Len(a,即列表的最右边)。 以下两个例子的理由与这两个例子相同。
a[-3:10]
[ 7,8,9 ]
a[-3:20]
[ 7,8,9 ]
4.1.3片开始索引位置超越边界
a[-10:-8]
[ 0,1 ]
a[-100:-8]
[ 0,1 ]
a[-100:2]
[ 0,1 ]
a[-10:2]
[ 0,1 ]
【解析】根据切片规则7,a[-100:-8]等效于a[-10:-8],a[-10:2]等效于a[-100:2]。 另一方面,a[-10:-8]与a[0:-8][a[0:2]等价],a[-10:2]与a[0:2]等价,因此具有上述那样的运转结果。
4.1.4片的开始索引或结束索引为负
a[-2:6]
[]
【解析】a[-2:6]相当于a[8:6],也相当于a[-2:6:1]和a[8:6:1]。 此时,step=1(省略),很容易看出切片结果集为空。
a[6:-2]
[ 6,7 ]。
【解析】a[6:-2]相当于a[6:8],也相当于a[6:-2:1]和a[6:8:1]。 在这种情况下,step=1(省略),结合"左闭右开"的原则,结果容易理解
4.1.5切片规则2的应用
a[6:2]
[]
a[-2:-6]
[]
【分析】符合切片规则2,很容易发现切片结果集为空。
a[-6:-2]
[ 4,5,6,7 ]
【解析】a[-6:-2]等效于a[4:8],结合“左闭右开”原则,给出了容易理解的结果集[a[4]、a[5]、a[6]、a[7][a[8]
4.1.6如果省略切片开始索引
a[:4]
[ 0,1,2,3 ]
a[:-4]
[ 0,1,2,3,4,5 ]
【解析】根据上述切片规则4.1,a[:4]等价于a[0:4],a[:-4]等价于a[0:-4]。 另外,a[0:-4]等价于a[0:6],与“左”结合
4.1.7省略切片截止索引时
a[4:]
[4、5、6、7、8、9]
a[-4:]
[ 6,7,8,9 ]
根据上述切片规则5.1,a[4:]是a[4:10](10=Len ) a ),a[-4:]是a[6:10],a[6:]是a [ 63333: ]
4.1.8如果切片开始索引和定界索引都被省略
a[:]
[0、1、2、3、4、5、6、7、8、9]
【解析】根据上述切片规则4.1和5.1,a[:]与a[0:10](10=len ) a ) )等价,但根据"左闭右开"的原则,结果集中存储有a[0],
4.2 .片式有两组冒号的
如果切片表达式中有两个冒号对,当step为1时,即上面只有一个冒号对时,可以省略第二个冒号对。 大部分情况已经说明了。
【前提】本部分使用与上述相同的结构和内容列表a,如下所示。
a=[ 0,1,2,3,4,5,6,7,8,9 ]
4.2.1 step>1时
不失一般性,以下讨论不妨假设step=2。先看下面的例子。
a[2:7:2]
[2, 4, 6]
a[:3:2]
[0, 2]
a[:-3:2]
[0, 2, 4, 6]
a[3::2]
[3, 5, 7, 9]
a[-3::2]
[7, 9]
【解析】首先注意到,step=2决定了切片方向是自左向右。当step>1时,切片起始索引值默认为0。对于负数形式的起始还是截止索引值都可以转换成等价的正数形式索引值(例如a[:-3:2]等价于a[:7:2]),a[-3::2] 等价于a[7::2])来分析的。再结合“左闭右开”原则,这一组例题应该不难理解,故细节的解释在此省略。
4.2.2 step为负整数时
例1
a[8:3:-1]
[8, 7, 6, 5, 4]
【解析】首先注意到,step为-1决定了切片方向是自右向左。本例中,切片起始索引为8,终止索引为3,再结合切片“左闭右开”原则,故切片结果集中元素有[a[8],a[7],a[6],a[5],a[4]],即[8,7,6,5,4]。
例2
a[10:0:-2]
[9, 7, 5, 3, 1]
【解析】首先注意到,step为-2决定了切片方向是自右向左。其次,根据上面切片原则7,切片的时候不存在索引越界情况,a[10]不存在,则继续往内分析,a[9]=9。于是,结合切片“左闭右开”原则和步长(即跨度)为2,故切片结果集中元素有[a[9],a[7],a[5],a[3],a[1]],即[9,7,5,3,1]。
例3
a[0:10:-2]
[]
【解析】首先注意到,step为-2决定了切片方向是自右向左。而切片初始索引为0,即列表的左边界,此时再向左切肯定没有元素可切了。因此,根据切片规则3,结果为空列表。
例4
a[:4:-1]
[9, 8, 7, 6, 5]
【解析】首先注意到,step为-1决定了切片方向是自右向左。此时,切片初始索引对应列表的最右边(=len(列表)),即有切片从索引10(实际从索引9开始,包含该索引)开始沿着自右向左的方向切片,直到索引4(不包含,依据是“左闭右开”),故有上述切片结果。
例5
a[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
【解析】首先注意到,step为-1决定了切片方向是自右向左。那么,接下来最关键的问题是搞清:在step为负数且切片初始索引和切片终止索引没有提供的情况下,这个切片初始索引和切片终止索引的值为多少。结合上面规则4.2和5.2,初始索引对应列表的最右边(=len(列表)),切片的截至索引位置为列表的最左边的左侧(即参与切片的子集中包含索引为0的元素)。当然,也可以简单根据上面规则6确定出最终的切片结果为列表中原来所有元素的倒序。
例6
a[5::-2]
[5, 3, 1]
【解析】首先注意到,step为-2决定了切片方向是自右向左。切片初始索引为5,结果集中自然包含a[5]。根据上面分析,本例中切片的截至索引位置为列表的最左边的左侧(即参与切片的子集中包含索引为0的元素)。从等价关系来分析的话,a[5::-2]等价于a[5:-11:-2](下标-11对应着下标-10再往左,类似于下标9再往右对应的下标10)。所以,有此例中运行结果。
思考题
a[0::-1]的结果是多少?
a[:-3:2] 的结果是多少?
a[1:6:-1] 的结果是多少?
a[-6::-1] 的结果是多少?
连续切片操作:a[:8][2:5][-1:] 的结果是多少?
a[2+1:3*2:7%3] 的结果是多少?
下列代码片断的运行结果是什么?
for i in range(1,100)[2::3][-10:]:
print(i)
【提示】利用range函数生成1-99的整数,然后取3的倍数,再取最后十个。
小结
理论上而言,只要条件表达式得当,可以通过单次或多次切片操作实现任意切取目标值。初看上去,切片操作的基本语法比较简单,但是深挖起来,并不简单。因此,如果不彻底搞清楚内在逻辑,也极容易产生错误,而且这种错误有时隐蔽得比较深,难以察觉。
作为补充,本文中提到的“左闭右开”原则,更细致地说法是“开始闭结束开”原则。即是说,开始索引对应元素参与切片运算,而结束索引对应元素并不参与切片运算。另外,步长值为负数,并且在省略切片起始索引或者切片终止索引情况下,这两种索引的默认值应当结合“切片不存在索引越界”原则进行正确理解。本文通过详细例子总结归纳了切片操作的各种情况。若有错误和不足之处请各位指正!