通常一个切片操作要提供三个参数[start:stop:step]
start是切片的起始位置
stop是切片的结束位置(不包括)
step可以不提供,默认值是1,步长值不能为0,不然会报错。
ValueError: slice step cannot be zero
list = [0,1,2,3,4,5,6,7,8,9]
当step为正数时,以list[start]元素位置开始, step做为步长到list[stop_]元素位置(不包括)为止,从左向右截取。start和stop不论是正数还是负数索引还是混用都可以,但是要保证 list[stop]元素的【逻辑】位置,必须在list[start]元素的【逻辑】位置右边,否则取不出元素。
print(list[0:4])
[0, 1, 2, 3]
print(list[1:-1])
[1, 2, 3, 4, 5, 6, 7, 8]
print(list[-8:8])
[2, 3, 4, 5, 6, 7]
当 step 是负数时,以list[start]元素位置开始, step做为步长到list[stop]元素位置(不包括)为止,从右向左截取,要保证 list[stop]元素的【逻辑】位置
必须在list[start]元素的【逻辑】位置左边,否则取不出元素。
print(list[5:2:-1])
[5, 4, 3]
print(list[7:-7:-1])
[7, 6, 5, 4]
start和stop在符合虚拟的逻辑位置关系时,start和stop的绝对值是可以大于length的。
print(list[-12:5:2])
[0, 2, 4]
start和stop都是可以省略的,例如 list[:],被省略的默认由其对应左右边界起始元素开始截取。
print(list[:])
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
常用的切片操作
在某个位置插入元素
list[3:3] = "a" print(list)
[0, 1, 2, 'a', 3, 4, 5, 6, 7, 8, 9]
list[5:5] = ["a","b"] print(list)
[0, 1, 2, 3, 4, 'a', 'b', 5, 6, 7, 8, 9]
list[5:5] = {"a":11} #插入字典类型元素时,只插入key值
print(list)
[0, 1, 2, 3, 4, 'a', 5, 6, 7, 8, 9]
在开始或结束位置之前插入元素
list[0:0] = ["a","b","c"] print(list)
['a', 'b', 'c', 0, 1, 2, 3, 4, 5, 6, 7, 8,9]
list[9:9] = "a" #index为9时,插入时不是结束位置 print(list)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 'a', 9]
list[10:10] = ["a","b","c"] #在结束位置插入字典类型元素时,index要大于length长度 print(list)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b','c']
在列表结束位置添加元素,相当于 list.append()函数,推荐使用append函数。
另外:extend() 函数用于在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表),向列表中追加序列(必须是可迭代的),可以是列表、元组、字典(加入key值)、集合。用法为:list.extend(seq)
替换多个元素
连续切片替换,替换的值的长度没有限制。
list[1:4] = "a" print(list)
[0, 'a', 4, 5, 6, 7, 8, 9]
list[1:4] = [11,22,33,44,55] print(list)
[0, 11, 22, 33, 44, 55, 4, 5, 6, 7, 8, 9]
对切片赋值,相当于替代原list中的切片部分,赋值的list不必与切片长度一致,也可以将切片赋值给新的变量,用以取原list中的一部分。
不连续切片替换
list[3:8:2] = ["a","b","c"] print(list)
[0, 1, 2, 'a', 4, 'b', 6, 'c', 8, 9]
list[3:8:2] = ["a","b"] print(list)
ValueError: attempt to assign sequence of size 2 to extended slice of size 3
list[3:8:2] = ["a","b","c","d"] print(list)
ValueError: attempt to assign sequence of size 4 to extended slice of size 3
不连续切片替换,替换的值的长度必须和切片一致,如果不一致,会报ValueError错误
删除切片
del list[2:5] print(list)
[0, 1, 5, 6, 7, 8, 9]
或者
list[2:5] = [] print(list)
[0, 1, 5, 6, 7, 8, 9]
list[2:5] = "" print(list)
[0, 1, 5, 6, 7, 8, 9]
切片的深浅拷贝问题
Python中列表切片是深拷贝,即被复制的对象作为一个新的个体独立存在,任意改变其一不会对另一个对象造成影响。即切片后的列表,赋值给新的对象。
对切片赋值,是在原对象的进行修改。
切片赋值给新的对象,是深拷贝得到的与原变量无关,是两个不同的对象
直接赋值,如 a = list , 是浅拷贝。
list = [0,1,2,3,4,5,6,7,8,9] a = list[1:5] a [3] = 121 print(list) print(a)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 121]
对于一维数组,在numpy的array中切片的操作与python列表的切片操作是相同的。
对于二维数组,索引规则为array[行,列]
importnumpy as np
nd =np.random.randint(10,100,size=(5,4))
nd
array([[55,34, 77, 15],
[39, 61, 43, 37],
[50, 71, 92, 17],
[94, 71, 25, 47],
[54, 20, 77,29]])
取行数据
nd[2,:]
array([50, 71, 92, 17])
nd[1:4,:]
array([[39,61, 43, 37],
[50, 71, 92, 17],
[94, 71, 25,47]])
.取列数据
nd[:,2]
array([77, 43, 92, 25, 77])
nd[:,0:2]
array([[55,34],
[39, 61],
[50, 71],
[94, 71],
[54, 20]])
.取一个数据块
nd[1:3,1:3]
array([[61,43],
[71, 92]])
.按照步长取值
nd[::2,::2]
array([[55, 77],
[50, 92],
[54, 77]])
另 数组切片后 可以赋值,只能是常数或者与切片形同的数组,常数遵循广播机制。
nd[::2,::2] = [111,222,333,444,555,666] # 报错
ValueError:could not broadcast input array from shape (6) into shape (3,2)
nd[::2,::2] = 1111
nd
array([[1111, 34, 1111, 15],
[ 39, 61, 222, 37],
[1111, 71, 1111, 17],
[ 94, 71, 444, 47],
[1111, 20, 1111, 29]])
数组切片是浅拷贝,味着数据不会被复制,任何修改都会直接反映到源数组上。
不想修改源数组,可以切片后,在加上 .copy(),就会生成新的数组。