3.2.1 更新列表
序列所拥有的特性,列表都有。在3.1节中所介绍的有关序列的操作,如索引、分片、相加、乘法等操作都适用于列表。本节将介绍一些序列中没有而列表中有的方法,这些方法的作用都是更新列表,如元素赋值、增加元素、删除元素、分片赋值和列表方法等。下面将逐一进行介绍。
1.元素赋值
前面的章节已经大量使用了赋值语句,赋值语句是最简单的改变列表的方式,如a=2就属于一种改变列表的方式。
创建一个列表,列表名为group,group中存放“序列号”上第一组所有5名同学的序号,通过编号标记某个特定位置的元素,对该位置的元素重新赋值,如group[1]=9,就可以实现元素赋值。
拿“序列号”上所有同学的序号来举例,第一组5位同学的序号分别是0、1、2、3、4。由于某种需要,需要序号为1的同学与序号为9的同学交换一下位置及所在的组,对于1和9号同学,各自交换一下座位即可,而导游则将序号为9的同学纳入第一组,序号为1的同学纳入第二组。
这个生活场景读者应该不难理解。而对于计算机来说,比这个生活场景更简单。创建列表group,赋值[0,1,2,3,4]后,计算机就在内存中为group变量开辟了一块内存空间,内存空间中存放数据的形式如图3-1所示。
当执行group[1]=9后,计算机会找到group变量,并找到索引下标为1的内存地址,将内存为1的地址空间的值擦除,再更改上9这个值,就完成了赋值操作,如图3-2所示。
图3-1 内存空间
图3-2 内存空间
在图3-2中可以看到,下标为1对应的数值已经更改为9了,此处为便于读者观察,在下标为1处用了一个波浪线作为特别提示。从此时开始,group列表中的值就变更为0、9、2、3、4了,后续再对group操作,就是在这个列表值的基础上进行操作了。
用代码实现上述操作如下:
>>> group=[0,1,2,3,4] >>> group[1]=9 #索引下标为1的元素重新赋值为9 >>> group [0, 9, 2, 3, 4] >>> group[3]=30 #同理,可以将索引下标为3的元素重新赋值为30 >>> group [0, 9, 2, 30, 4]
这里不要忘记索引下标的编号是从0开始的。
由输出结果可以看到,可以根据索引下标编号对列表中某个元素重新赋值。
既然可以重新赋值,是否可以对列表中的元素赋不同类型的值呢?对上面得到的group列表,在交互模式下做如下尝试:
>>> group[2]='xiaomeng' #对编号为2的元素赋值,赋一个字符串 >>> group [0, 9, 'xiaomeng', 30, 4] >>> type(group) <class 'list'> >>> type(group[1]) #别忘了查看类型函数的使用 <class 'int'> >>> type(group[2]) <class 'str'>
由输出结果可以看到,可以对一个列表中的元素赋以不同类型的值。在上面的示例中,列表group中既有int类型的值,也有str类型的值。
假如对列表赋值时,使用的索引下标编号超过了列表中的最大索引下标编号,是否可以赋值成功?得到结果会是怎样的?继续对group列表操作,group列表中当前有5个元素,最大索引下标是4,即group[4],这里尝试对group[5]赋值,在交互模式下输入:
>>> group [0, 9, 'xiaomeng', 30, 4] >>> group[5]='try' Traceback (most recent call last): File "<pyshell#134>", line 1, in <module> group[5]='try' IndexError: list assignment index out of range
在上面的示例中,group列表的最大索引下标编号是4,当给索引下标编号为5的元素赋值时出错,错误提示的信息是:列表索引超出范围。
提示
不能为一个不存在元素的位置赋值,若强行赋值,程序会报错。
2.增加元素
由上面元素赋值的示例可以看到,不能为一个不存在的元素位置赋值,列表一旦创建,就不能再向这个列表中增加元素了。
不能向列表中增加元素这种情况可能会让我们比较难堪,毕竟在实际项目应用中,一个列表到底要创建为多大,经常是不能预先知道的。
那么,这种问题该怎么处理呢?列表增加元素的操作在实际应用中会有比较多的应用场景,也是一个高频次的操作,Python中是否提供了对应的方法帮助我们做这件事情呢?
答案是肯定的。接着上面的示例,下面尝试将字符串try添加到group列表中。在交互模式下 输入:
>>> group [0, 9, 'xiaomeng', 30, 4] >>> group.append('try') >>> group [0, 9, 'xiaomeng', 30, 4, 'try']
由示例输出结果看到,在Python中提供了一个append()方法,该方法可以帮助我们解决前面遇到的困惑。
append()方法是一个用于在列表末尾添加新对象的方法。append()方法的语法格式如下:
list.append(obj)
此语法中,list代表列表,obj代表需要添加到list列表末尾的对象。
提示
append()方法的使用方式是list.append(obj),list要为已经创建的列表,obj不能为空。
对于append()方法的使用,需要补充说明:append()方法操作列表时,返回的列表不是一个新列表,而是直接在原来的列表上做修改,然后将修改过的列表直接返回。如果是创建新列表,就会多出一倍的存储空间。以group列表为例,未使用append()方法之前,group列表中的内容是[0, 9, 'xiaomeng', 30, 4],这是已经占用了一块存储空间的值。使用append()方法后,若创建了新列表,就会在内存中再开辟一块新的存储空间,新开辟的存储空间中存放的内容是[0, 9, 'xiaomeng', 30, 4, 'try'],和原列表比起来,就相当于增加了一倍的存储空间。而直接修改列表的情形会是这样的:内容是[0, 9, 'xiaomeng', 30, 4]的存储空间继续占有,使用append()方法后,会在现有的存储空间中增加一小块内存,用来存放新增加的try字符串,相对于原列表,仅仅增加了try字符串所占据的存储,而不是增加一倍的存储空间。
使用append()方法,可以向列表中增加各种类型的值。
继续操作group列表,append()使用的示例如下:
>>> group [0, 9, 'xiaomeng', 30, 4, 'try'] >>> group.append('test') #向列表添加字符串 >>> group [0, 9, 'xiaomeng', 30, 4, 'try', 'test'] >>> group.append(3) #向列表添加数字 >>> group [0, 9, 'xiaomeng', 30, 4, 'try', 'test',3]
3.删除元素
由上面的示例输出接口可以得知:可以向数字序列中添加字符串,也可以向字符串序列中添加数字。
前面学习了向列表中增加元素,可以使用append()方法来实现。列表中既然可以增加元素,那是否可以删除元素呢?
继续操作group列表,示例如下:
>>> group [0, 9, 'xiaomeng', 30, 4, 'try', 'test'] >>> len(group) #使用序列中获取长度的函数 7 >>> del group[6] #删除最后一个元素,注意索引下标与序列长度的关系 >>> print('删除最后一个元素后的结果:',group) 删除最后一个元素后的结果: [0, 9, 'xiaomeng', 30, 4, 'try'] >>> len(group) 6 >>> group [0, 9, 'xiaomeng', 30, 4, 'try'] >>> del group[2] #删除索引下标为2的元素 >>> print('删除索引下标为2的元素后的结果:',group) 删除索引下标为2的元素后的结果: [0, 9, 30, 4, 'try'] >>> len(group) 5
由输出结果可以看到,使用del可以删除列表中的元素。
上面的示例中使用del删除了group列表中的第7个元素,删除元素后,原来有7个元素的列表会变成有6个元素的列表。
使用del除了可以删除列表中的字符串,也可以删除列表中的数字。
继续操作group列表,在交互模式下输入:
>>> group [0, 9, 30, 4, 'try'] >>> len(group) 5 >>> del group[3] >>> print('删除索引下标为3的元素后的结果:',group) 删除索引下标为3的元素后的结果: [0, 9, 30, 'try'] >>> len(group) 4
由输出结果可以看到,已经从group列表中删除了对应的数字。
除了删除列表中的元素,del还能用于删除其他元素,具体将在后续章节做详细介绍。
4.分片赋值
分片赋值是列表一个强大的特性。已经在3.1节讲解过分片的定义与实现。
在继续往下之前需要补充一点:如前面所说,通过a=list()的方式可以初始化一个空的列表。但若写成如下形式:
list(str)或a=list(str)
则list()方法会将字符串str转换为对应的列表,str中的每个字符将被转换为一个列表元素,包括空格字符。list()方法可以直接将字符串转换为列表。该方法的一个功能就是根据字符串创建列表,有时这么操作会很方便。list()方法不仅适用于字符串,所有类型的序列它都适用。
>>> list('北京将举办2020年的冬奥会') ['北', '京', '将', '举', '办', '2', '0', '2', '0', '年', '的', '冬', '奥', '会'] >>> greeting=list('welcome to beijing') >>> greeting ['w', 'e', 'l', 'c', 'o', 'm', 'e', ' ', 't', 'o', ' ', 'b', 'e', 'i', 'j', 'i', 'n', 'g'] >>> greeting[11:18] ['b', 'e', 'i', 'j', 'i', 'n', 'g'] >>> greeting[11:18]=list('china') >>> greeting ['w', 'e', 'l', 'c', 'o', 'm', 'e', ' ', 't', 'o', ' ', 'c', 'h', 'i', 'n', 'a']
由输出结果可以看到,可以直接使用list()将字符串变换为列表,也可以通过分片赋值直接对列表进行变更。
示例中我们首先将字符串“北京将举办2020年的冬奥会”使用list()方法转变为列表,接着将字符串“welcome to beijing”也使用list()方法转变为列表,并将结果赋值给greeting列表。最后通过分片操作变更greeting列表中索引下标编号为11到18之间的元素,即将beijing替换为china。
除了上面展示的功能,分片赋值还有什么强大的功能呢?先看下面的示例:
>>> greeting=list('hi') >>> greeting ['h', 'i'] >>> greeting[1:]=list('ello') >>> greeting ['h', 'e', 'l', 'l', 'o']
分析如下:首先给greeting列表赋值['h', 'i'],后面通过列表的分片赋值操作将编号1之后的元素变更,即将编号1位置的元素替换为e,但是编号2之后没有元素,怎么能操作成功呢?并且一直操作到编号为4的位置呢?
这就是列表的分片赋值的另一个强大的功能:可以使用与原列表不等长的列表将分片进行替换。
除了分片替换,列表的分片赋值还有哪些新功能呢?接着看下面的示例:
>>> field=list('ae') >>> field ['a', 'e'] >>> field[1: 1]=list('bcd') >>> field ['a', 'b', 'c', 'd', 'e'] >>> goodnews=list('北京将举办冬奥会') >>> goodnews ['北', '京', '将', '举', '办', '冬', '奥', '会'] >>> goodnews[5: 5]=list('2022年的') >>> goodnews ['北', '京', '将', '举', '办', '2', '0', '2', '2', '年', '的', '冬', '奥', '会']
由输出结果可以看到,使用列表的分片赋值功能,可以在不替换任何原有元素的情况下在任意位置插入新元素。读者可自行尝试在上面示例的其他位置进行操作。
当然,上面的示例程序的实质是“替换”了一个空分片,实际发生的操作是在列表中插入了一个列表。
该示例的使用是否让你想起了前面使用过的append()方法,不过分片赋值比append()方法的功能强大很多,append()方法只能在列表尾部增加元素,不能指定元素的插入位置,并且一次只能插入一个元素;而分片赋值可以在任意位置增加元素,并且支持一次插入多个元素。
看到这里,是否同时想起了前面删除元素的操作,分片赋值是否支持类似删除的功能呢?
分片赋值中也提供了类似删除的功能。示例如下:
>>> field=list('abcde') >>> field ['a', 'b', 'c', 'd', 'e'] >>> field[1: 4]=[] >>> field ['a', 'e'] >>> field=list('abcde') >>> del field[1: 4] >>> field ['a', 'e'] >>> goodnews=list('北京将举办2022年的冬奥会') >>> goodnews ['北', '京', '将', '举', '办', '2', '0', '2', '2', '年', '的', '冬', '奥', '会'] >>> goodnews[5: 11]=[] >>> goodnews ['北', '京', '将', '举', '办', '冬', '奥', '会']
从上面的输出结果可以看到,通过分片赋值的方式,将想要删除的元素赋值为空列表,可以达到删除对应元素的效果。并且列表中的分片删除和分片赋值一样,可以对列表中任意位置的元素进行删除。