在切片和区间操作里不包括区间范围内的最后一个元素是Python的风格。这样做的好处:
- 当只有最后一个位置信息时,我们也可以快速看出切片和区间里有几个元素:range(3)和my_list(:3)都返回三个元素
- 当起止位置都可见时,我们可以快速计算出切片和区间长度,用最后一个数减去第一个下标(stop-start)即可
- 可以利用任意一个下标来把序列分割成两个不重叠的部分,只要写成my_list[:x]和my_list[x:]就可以了
1、对对象进行切片
"""
s = [a:b:c],在a,b间,以c为步长取值,c为负值意味着反向取值
"""
"""Example 1"""
s = 'bicycle'
s = [::3] # s = 'bye'
"""Example 2"""
s = 'bicycle'
s = [::-1] # s = 'elcycib'
"""Example 3"""
s = 'bicycle'
s = [::-2] # s = 'eccb'
2、给切片赋值
"""切片除了可以提取序列里的内容,还可以用来就地修改可变序列"""
l = list(range(10)) # l = [0,1,2,3,4,5,6,7,8,9]
l[2:5] = [20,30] # l = [0,1,20,30,5,6,7,8,9]
del l[5:7] # l = [0,1,20,30,5,8,9]
l[3::2] = [11,22] # l = [0,1,20,11,5,22,9]
l[2:5] = 100 # ① 会报错
"""
Traceback (most recent call last):
File "D:\PycharmProjects\fluentPython\chapter2\test.py", line 6, in <module>
l[2:5] = 100
TypeError: can only assign an iterable
"""
l[2:5] = [100] # l = [0, 1, 100, 22, 9]
"""
①:如果赋值的对象是一个切片,那么赋值语句的右侧必须是一个可迭代对象。
即使只有单独的一个值,也要把它转换成可迭代的序列
"""
3、对序列使用+和*
+和*都遵循不修改原有的操作对象,而是构建一个全新的序列的规律
"""
如果想要把一个序列复制几份再拼接起来,更快捷的做法是把这个序列乘以一个整数
"""
l = [1,2,3]
l = l * 5 # l = [1,2,3,1,2,3,1,2,3,1,2,3,1,2,3]
a = 'abcd'
a = 5 * 'abcd' # a = 'abcdabcdabcdabcdabcd'
4、建立由列表组成的列表
有时候我们需要初始化一个嵌套着几个列表的列表。
"""列表推导式"""
board = [['_'] * 3 for i in range(3)]
# [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
board[1][2] = 'X'
# [['_', '_', '_'], ['_', '_', 'X'], ['_', '_', '_']]
"""含有3个指向同一列表的引用是毫无用处的"""
weird_board = [['_'] * 3] * 3
# [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
weird_board[1][2] = '0'
# [['_', '_', '0'], ['_', '_', '0'], ['_', '_', '0']]
"""
外面的列表其实包含3个指向同一个列表的引用,当我们不做修改时他们看起来还好,
一旦试图修改第一行第二列的元素,就立马暴露了列表内的3个引用指向同一个对象的事实。
"""
row = ['_'] * 3
rows = []
for i in range(3):
rows.append(row)
# [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
rows[1][2] = '1'
# [['_', '_', '1'], ['_', '_', '1'], ['_', '_', '1']]
"""
weird_board错误的本质和rows代码一样,追加同一个对象到rows
"""
PS:《流畅的Python》个人学习笔记,如果觉得不错,最好支持原书。