2.1.4 切片
切片也是Python序列的重要操作之一,在形式上,切片使用2个冒号分隔的3个数字来完成,第一个数字表示切片的开始位置(默认为0),第二个数字表示切片的截止(但不包含)位置(默认为列表长度),第三个数字表示切片的步长(默认为1),当步长省略时同事可以省略最后一个冒号。
切片适用于列表、元组、字符串、range对象等类型,应用于列表时具有最为强大的功能。可以使用切片来截取列表中的任何部分返回得到一个新的列表,也可以通过切片来修改和删除列表中的部分元素,甚至可以通过切片操作作为列表对象增加元素。
练习篇:
1 使用切片获取列表中的部分元素
1 #使用切片可以返回列表原有元素的一个“子集”。与使用下标访问列表元素的方法不同,切片操作不会因为下标越界而抛出异常,而是简单地在列表尾部截断或者返回一个空列表,
代码具有更强的健壮性。
2
3 >>> alIST = [3,4,5,6,7,9,11,13,15,17]
4 >>>
5 >>>
6 >>> alIST[::] #返回包含原列表中所有元素的新列表
7 [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
8 >>>
9 >>> alIST[::-1] #返回包含原列表中所有元素的逆序列表
10 [17, 15, 13, 11, 9, 7, 6, 5, 4, 3]
11 >>>
12 >>> alIST[::2] #隔一个元素取一个元素,获取偶数位置的元素
13 [3, 5, 7, 11, 15]
14 >>>
15 >>> alIST[1::2] #隔一个元素取一个元素,获取奇数位置的元素
16 [4, 6, 9, 13, 17]
17 >>>
18 >>> alIST[3:6] #指定切片的开始位置和结束位置
19 [6, 7, 9]
20 >>>
21 >>> alIST[0:100] #切片的开始位置大于列表长度是,从列表尾部截断
22 [3, 4, 5, 6, 7, 9, 11, 13, 15, 17]
23 >>>
24 >>> alIST[100:0] #切片的开始位置大于列表长度是,返回空列表
25 []
26 >>>
27 >>> alIST[100] #抛出异常,不允许越界访问
28 Traceback (most recent call last):
29 File "<pyshell#84>", line 1, in <module>
30 alIST[100]
31 IndexError: list index out of range
32 >>>
2 使用切片对列表元素进行增、删、改
可以使用切片操作来快速实现很多目的,例如,原地修改列表内容,列表元素的增、删、改以及元素替换等操作都可以通过切片来实现,并且不影响列表对象的内存地址。
1 >>> a = [3,5,7]
2 >>>
3 >>> a[len(a):]
4 []
5 >>>
6 >>> a[len(a):] = [9] #在列表尾部增加元素
7 >>> a
8 [3, 5, 7, 9]
9 >>>
10 >>> a[:3] = [1,2,3] #替换列表元素
11 >>> a
12 [1, 2, 3, 9]
13 >>>
14 >>> a[:3] = [] #删除列表元素
15 >>> a
16 [9]
17 >>>
18 >>> a = list(range(10))
19 >>>
20 >>> a
21 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
22 >>>
23 >>> 9 // 2
24 4
25 >>> a[::2] = [0] * (len(a) //2 ) #替换列表元素
26 >>> a
27 [0, 1, 0, 3, 0, 5, 0, 7, 0, 9]
28 >>>
29 >>> a[3:3] = [4,5,6] #在列表指定位置插入元素
30 >>>
31 >>> a
32 [0, 1, 0, 4, 5, 6, 3, 0, 5, 0, 7, 0, 9]
33 >>>
34 >>>
35 >>> len(a)
36 13
37 >>>
38 >>> a[20:30] = [3] * 2 #这样也可以在列表尾部追加元素,注意切片的范围
39 >>>
40 >>> a
41 [0, 1, 0, 4, 5, 6, 3, 0, 5, 0, 7, 0, 9, 3, 3]
42 >>>
43
44
45 #另外,可以结合使用del命令与切片结合来删除列表中的部分元素。
46
47 >>>a = [1,2,3,9,11]
48
49 >>>del a[:3]
50
51 >>>a
52 [9,11]
53
54
55 #切片返回的是列表元素的浅复制,与列表对象的直接赋值并不一样
56
57 >>> a = [3,5,7]
58 >>> b = a #b与a指向同一个内存
59 >>> b
60 [3, 5, 7]
61 >>> b[1] = 8
62 >>> a
63 [3, 8, 7]
64 >>>
65 >>> a == b #两个列表的值是相等的
66 True
67 >>>
68 >>>a is b #两个列表是同一个对象
69 True
70
71 >>> id(a) == id(b) #两个列表的内存地址相等
72 True
73 >>>
74 >>>
75 >>> a = [3,5,7]
76 >>>
77 >>> b = a[:] #切片,浅复制
78 >>>
79 >>> a == b #两个列表的值是相等的
80 True
81 >>>
82 >>> a is b #浅复制,不是同一个对象
83 False
84 >>>
85 >>> id(a) == id(b) #两个列表对象的地址不相等
86 False
87 >>>
88 >>>
89 >>> id(a[0]) == id(b[0]) #不要怀疑,相同值在内存中仍然只有一份
90 True
91 >>>
92 >>> b[1] = 8 #修改列表b中的元素值不会影响列表a中的元素值
93 >>> a
94 [3, 5, 7]
95 >>>
96 >>> b #b列表的元素值发生改变
97 [3, 8, 7]
98 >>>
99 >>> a == b
100 False
101 >>>
102 >>> a is b
103 False
104 >>>
105
106
107
108 #顺便再补充一点,虽然直接把一个列表变量赋值给另一个变量时两个变量指向同一个内存地址,但是把一个列表分别赋值给2个变量时就不是这样的情况了,例如:
109
110 >>> x = [1,2,3]
111 >>> y = [1,2,3]
112 >>> id(x) == id(y)
113 False
114 >>>
115 >>> y.append(4) #改变列表y中的元素值并不会影响列表x中的元素值
116 >>> x
117 [1, 2, 3]
118
119 >>> y
120 [1, 2, 3, 4]
121 >>>
122
123
124 #当列表中包含其他可变序列是,情况变得更加复杂,例如:
125
126 >>> x = [[1],[2],[3]]
127 >>>
128 >>> y = x[:]
129 >>>
130 >>> y
131 [[1], [2], [3]]
132 >>>
133 >>>
134 >>> y[0] = [4] #直接修改y中下标为0的元素值,不影响x中的元素值
135 >>> y
136 [[4], [2], [3]]
137 >>>
138 >>> x
139 [[1], [2], [3]]
140 >>>
141 >>> y[0].append(5)
142 >>> y
143 [[4, 5], [2], [3]]
144 >>>
145 >>> x
146 [[1], [2], [3]]
147 >>>
148 >>> y[1].append(5) #通过列表对象的方法原地增加元素,影响x中的元素值
149 >>> y
150 [[4, 5], [2, 5], [3]]
151 >>>
152 >>> x
153 [[1], [2, 5], [3]]
154 >>>
155
156 #上述这段代码的理解上需要记住两点:
157 #(1)Python采用的是基于值的内存管理模式;
158 #(2)Python变量中并不直接存放值,而是存放值的引用。Python的变量更像一个容器,盛的就是实际值的内存地址,也可能是另外一个容器的地址。
159
160
161
162 #注意:使用切片修改列表元素值时,如果左侧切片是连续的,那么等号两侧的列表长度可以不一样;如果左侧切片不连续,则右侧列表中元素个数必须与必须与左侧相等;使用del命令
163 #和切片删除列表中部分元素是,切片可以不连续。例如:
164
165 >>> x = list(range(10))
166 >>>
167 >>> x[::2] = [3,5] #等号两侧不等长,抛出异常
168 Traceback (most recent call last):
169 File "<pyshell#234>", line 1, in <module>
170 x[::2] = [3,5]
171 ValueError: attempt to assign sequence of size 2 to extended slice of size 5
172 >>>
173 >>>
174 >>> x[::2] = [1,1,1,1,1] #等号两侧等长,可以执行
175 >>>
176 >>> x
177 [1, 1, 1, 3, 1, 5, 1, 7, 1, 9]
178 >>>
179 >>> del x[::2] #可以删除列表中不连续的元素
180 >>>
181 >>> x
182 [1, 3, 5, 7, 9]
183 >>>