python学习之“切片操作从入门到精通”

时间:2021-05-28 21:26:12

在python学习开发的过程中,我们总是不断的要对List(列表),Tuple(元组)有取值操作:假如我们有一个列表List1现在想取出1其中的前5个元素,改怎么操作呢?

1 >>> List1 = ['zhangxueyou','liuyifei','liudehua','huyidao','haodada','wumengda','zhouxingchi','chenglong','Jack','linzhilin']
2 >>> List1
3 ['zhangxueyou', 'liuyifei', 'liudehua', 'huyidao', 'haodada', 'wumengda', 'zhouxingchi', 'chenglong', 'Jack', 'linzhilin']
4 >>> #比较笨的办法是直接取值
5 ... 
6 >>> [List1[1],List1[2],List1[3],List1[4],List1[5]]
7 ['liuyifei', 'liudehua', 'huyidao', 'haodada', 'wumengda']
8 >>> 

以上的直接取值的方法是存在很大的局限性的,假如现在想取前一百万个值的话,是不是就没有办法了呢?但是你还是可以用循环完成:

 1 >>> List1
 2 ['zhangxueyou', 'liuyifei', 'liudehua', 'huyidao', 'haodada', 'wumengda', 'zhouxingchi', 'chenglong', 'Jack', 'linzhilin']
 3 >>> List2 = []
 4 >>> List2
 5 []
 6 >>> n = 5
 7 >>> for i in range(n):
 8 ...     List2.append(List1[i])
 9 ... 
10 >>> List2
11 ['zhangxueyou', 'liuyifei', 'liudehua', 'huyidao', 'haodada']
12 >>> 

但是,对这种经常取指定索引的范围的操作,假如你使用循环的话使可以解决的,但是相对更好的方法而言,此操作是相当繁琐和费事的。因此python就提供了一个比较重量级的方法:切片(Slice)操作,能大大的简化操作。

对于同样的问题,只需要简单的一个切片操作就可以取得同样的效果:

 1 >>> List1
 2 ['zhangxueyou', 'liuyifei', 'liudehua', 'huyidao', 'haodada', 'wumengda', 'zhouxingchi', 'chenglong', 'Jack', 'linzhilin']
 3 >>> #比较笨的办法是直接取值
 4 ... 
 5 >>> [List1[1],List1[2],List1[3],List1[4],List1[5]]
 6 ['liuyifei', 'liudehua', 'huyidao', 'haodada', 'wumengda']
 7 >>> 
 8 >>> 
 9 >>> 
10 >>> 
11 #使用循环取值:比较繁琐
12 >>> List1
13 ['zhangxueyou', 'liuyifei', 'liudehua', 'huyidao', 'haodada', 'wumengda', 'zhouxingchi', 'chenglong', 'Jack', 'linzhilin']
14 >>> List2 = []
15 >>> List2
16 []
17 >>> n = 5
18 >>> for i in range(n):
19 ...     List2.append(List1[i])
20 ... 
21 >>> List2
22 ['zhangxueyou', 'liuyifei', 'liudehua', 'huyidao', 'haodada']
23 >>> #切片操作的演示:
24 ... 
25 >>> List1[0:4]
26 ['zhangxueyou', 'liuyifei', 'liudehua', 'huyidao']
27 >>> List1[0:5]
28 ['zhangxueyou', 'liuyifei', 'liudehua', 'huyidao', 'haodada']
29 >>> 

注意:List1[0:5]表示的含义是,从索引0开始直到取到5个元素,因此,取到的元素索引为:0,1,2,3,4但是不包含第六个数的索引5,这里刚好取到了5个元素。故,记住切片的口诀就是:“顾头不顾尾”。假如你的第一个索引是“0”,那么你可以省略不写:

1 >>> List1
2 ['zhangxueyou', 'liuyifei', 'liudehua', 'huyidao', 'haodada', 'wumengda', 'zhouxingchi', 'chenglong', 'Jack', 'linzhilin']
3 >>> #索引为0的情况可以省略
4 ... 
5 >>> List1[:5]
6 ['zhangxueyou', 'liuyifei', 'liudehua', 'huyidao', 'haodada']
7 >>> List1[0:5]
8 ['zhangxueyou', 'liuyifei', 'liudehua', 'huyidao', 'haodada']
9 >>> 

python是支持负索引的,即List1[-1],List1[-2],同样,切片也是支持负索引的:

1 >>> List1
2 ['zhangxueyou', 'liuyifei', 'liudehua', 'huyidao', 'haodada', 'wumengda', 'zhouxingchi', 'chenglong', 'Jack', 'linzhilin']
3 >>> List1[-2:]
4 ['Jack', 'linzhilin']
5 >>> List1[-2:-1]
6 ['Jack']
7 >>> List1[:-1]
8 ['zhangxueyou', 'liuyifei', 'liudehua', 'huyidao', 'haodada', 'wumengda', 'zhouxingchi', 'chenglong', 'Jack']
9 >>> #记住:倒数第一个元素的索引采用负索引的话就是-1

切片在python开发过程中是十分有用的,首先我们创建一个0-199的数列:

1 >>> List3 = range(199)
2 >>> List3
3 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198]
4 >>> 

然后,我们就可以在其中取出任意一段长度值:

1 >>> List3[:50]#取出前50个数
2 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
3 >>> List3[:-100]#取出前50个数
4 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98]

还可以添加“步长“取值:

1 >>> List3
2 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198]
3 >>> List3[:100:5]#步长为5
4 [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
5 >>> 

甚至什么都不写,只写[:]就可以原样复制一个list:

1 >>> List1[:]
2 ['zhangxueyou', 'liuyifei', 'liudehua', 'huyidao', 'haodada', 'wumengda', 'zhouxingchi', 'chenglong', 'Jack', 'linzhilin']
3 >>> List2[:]
4 ['zhangxueyou', 'liuyifei', 'liudehua', 'huyidao', 'haodada']
5 >>> List3[:]
6 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198]
7 >>> 

tuple也是一种list,唯一区别是tuple不可变。因此,tuple也可以用切片操作,只是操作的结果仍是tuple:

1 >>> tuple1 = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
2 >>> tuple1[:10]
3 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
4 >>> tuple1[:-8]
5 (1, 2, 3, 4, 5, 6, 7)
6 >>> 

字符串'xxx'或Unicode字符串u'xxx'也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串:

1 >>> "ABCDEFGHIJKLMNOPQRST"[:5]
2 'ABCDE'
3 >>> "ABCDEFGHIJKLMNOPQRST"[:-6]
4 'ABCDEFGHIJKLMN'
5 >>> 

在很多编程语言中,针对字符串提供了很多各种截取函数,其实目的就是对字符串切片。Python没有针对字符串的截取函数,只需要切片一个操作就可以完成,非常简单。

注意:当你的索引超出你要索引的元组或者列表的范围的时候是不会报任何错误的,只会按照列表或者元组的的、最大长度来显示:

1 >>> List3
2 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198]
3 >>> List3[:231] #这里明显已经超出了列表的范围
4 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198]

python切片中的高级操作:

1. 切片的原理分析:

list的切片,内部是调用__getitem__,__setitem__,__delitem__和slice函数。而slice函数又是和range()函数相关的。

给切片传递的键是一个特殊的slice对象。该对象拥有可描述所请求切片方位的属性,切片的含义和演示:

1 >>> List4 = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
2 >>> List4
3 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
4 >>> x = List4[1:10] #x = List4.__getitem__(slice(1,10,None))
5 >>> List4[1:5]=[100,111,122] #List4.setitem__(slice(1,3,None),[100,111,122])
6 >>> del List4[1:4] #List4.del__delitem__(slice(1,4,None))
7 >>> List4
8 [1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
9 >>> 

带步长的python切片:

1 >>> List4
2 [1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
3 >>> List4[0:20:2] #其中2为步长值
4 [1, 7, 9, 11, 13, 15, 17, 19]
5 >>> 

注意:步进值为step

当step > 0 时

切片从 start(含start)处开始,到end(不含end)处结束,**从左往右**,每隔(step-1)(索引之间的差仍为step,但相隔的元素是step-1个)个元素进行一次截取。

这时,start 指向的位置应该在end指向的位置的左边,否则返回值为空

当step < 0 时

切片从 start(含start)处开始,到end(不含end)处结束,**从右往左**,每隔(step-1)(索引之间的差仍为step,但相隔的元素是step-1个)个元素进行一次截取。

这时,start 指向的位置应该在end指向的位置的右边,否则返回值为空

这里有一个比较经典的字符串反向的例子:

1 >>> strin = "Hello World!"
2 >>> strin[::-1]
3 '!dlroW olleH'
4 >>> 

切片的边界问题:

1 s=[1,2,3,4]       # S 上界为 0 下界为 4
2 s[-100:100]       #返回 [1,2,3,4] -100超出了上界,100超出了下界:等价于 s[0:4]
3 s[-100:-200]      #返回 [] -100,-200均超出了上界,自动取上界:等价于s[0:0]
4 s[100:200]        #返回 [] 100,200均超出了下界,自动取下界值:等价于s[4:4]
5 s[:100]           #返回 [1,2,3,4] 开始值省略表示从第0个开始
6 s[0:]             #返回 [1,2,3,4] 结束值为空表示到最后一个结束

2. 切片的扩展知识:

 1 >>> id(List4)
 2 140115516658320
 3 #直接通过列表来赋值 List5 = List4,指向的内存地址空间是不变的,都是(140115516658320),无论删除List4还是List5这个列表都会被删除,即List4和List5都没有元素了。
 4 >>> List5 = List4
 5 >>> List5
 6 [1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
 7 >>> List4
 8 [1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
 9 >>> id(List5)
10 140115516658320
11 #但是,通过切片来命名的两个列表他们指向的内存地址编号是不同的,140115516658320 !=  140115516604784
12 >>> List6 = List5
13 >>> id(List6)
14 140115516658320
15 >>> List6 = List4[:]
16 >>> id(List6)
17 140115516604784
18 >>> #地址改变
19 ... 
20 >>>