切割序列类型的方法
切割序列类型的方法
Python提供了列表切片的方法。这种切片(slice)操作,使开发者能够轻易地访问列表中某些元素。最简单的用法,就是对内置的list、str、bytes进行切割。切割操作还可以眼神到实现了__getitem__和__setitem__这两个类方法上。切割操作的基本写法是somelist[start:end],其中start是起始索引,end是结束索引,结束索引会自动减一。
一 切片基本使用
list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print(f'第1-4个值: {list1[:4]}') print(f'最后4个值: {list1[-4:]}') print(f'中间两个值: {list1[3: -3]}')
>>> 第1-4个值: ['a', 'b', 'c', 'd'] >>> 最后4个值: ['e', 'f', 'g', 'h'] >>> 中间两个值: ['d', 'e']
二 要点
① :start处不要写0
如果从列表开头获取值,start处不要写0,而是应该把它留空,这样代码看起来会清爽一些。
list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] # 不报错就代表断言成功 assert list1[:5] == list1[0:5]
② :end处应该留空
如果切片一直取到末尾,end处就应该留空,就算写了值也是多余的。
list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] # 不报错就代表断言成功 assert list1[5:] == list1[5:len(list1)]
③ :start或end索引越界也不会出现问题
在切割列表时,即便start或end索引越界也不会出现问题。我们可以利用这一特性,限定输入序列类型的最大长度。
# 切片越界不会报错 first_end = list1[:100] last_end = list1[-100:] print(first_end) print(last_end) # 注意: 切片start若为-0时,则会在原来列表中拷贝一份 last_end2 = list1[-0:] print(last_end2) # 反而访问列表中单个元素的时候,下标越界就会出现异常 print(list1[100]) # >>> IndexError: list index out of range
④ :对原列表进行切割之后, 会产生另外一份全新的列表。在切割后得到的新列表上进行修改,不会影响原列表。
# 切片过后的列表赋值给b b = list1[4:] print('修改前', b) # 对b进行修改不会影响原列表list1 b[1] = 99 print('修改后', b) print('', list1)
⑤ :在赋值时对左侧列表使用切割操作,会把该列表中处在指定范围内的值替换为新值。与元组的赋值不同,元组切片的长度必须个数相等。但是列表的切片长度无需个数相等。位于切片范围之前及之后的值都保留不变,列表会根据新值的个数相应地扩展与收缩。
# 元组切片赋值(元组切片的长度必须个数相等) tuple1 = (1, 2, 3, 4, 5, 6, 7) t1, t2, t3 = tuple1[:3] print(t1, t2, t3) # 1 2 3 t3, t4, t5 = tuple1[:2] print(t3, t4, t5) >>> ValueError: not enough values to unpack (expected 3, got 2) # 列表切片赋值(列表切片的长度必须个数相等) list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] print('改变前', list1) # 缩短 list1[:5] = [1, 2, 3] print('改变后', list1) >>> 改变前 ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] >>> 改变后 [1, 2, 3, 'f', 'g', 'h'] # 扩张 list1[:5] = [1, 2, 3, 4, 5, 6,7] print('改变后', list1) >>> 改变前 ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] >>> 改变后 [1, 2, 3, 4, 5, 6, 7, 'f', 'g', 'h']
⑥ :如果列表赋值操作的右侧列表使用切片,而且把切片的起、止位置都留空,则会产生一份原列表的拷贝。
list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] list2 = list1[:] # 值相等,但id不相等 assert list2 == list1 and list2 is not list1
⑦ :如果列表赋值操作的左侧使用切片,而没有指定起、止索引,那么就会把右侧列表拷贝一月份,将这份拷贝的值替换左侧列表中的全部内容,并且指向同一个内存地址,而不会重新分配新的列表。
list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] list2 = list1 print('改变前: ', list2) list1[:] = [1, 2, 3] # 断言表示list1与list2的id相等 assert list1 is list2 print('改变后: ', list1) >>> 改变前: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] >>> 改变后: [1, 2, 3]
总结:
1.不要写多余的代码: 当start索引为0, 或end索引为序列长度时,应该将其省略。
2.切片操作不会计较start与end索引是否越界,这使我们很容易就能从序列的前或后开始,并对其进行范围固定的切片操作。
3.对list赋值的时候,如果使用切片操作,就会把原列表中所处范围的值替换成新值,即便它们的长度不同也依然可以替换。