2 序列概述
- 常用序列结构有列表、元组、字符串、字典、集合以及range等对象也支持很多类似操作
- 列表、元组、字符串(有序序列)支持双向索引
- 逆向:最后一个元素下标为-1,倒数第二个为-2以此类推
- 正向:第一个元素下标为0,第二个元素下标为1
2.1 列表
- 列表是python中内置有序可变序列
- 当列表元素增加或删除时,列表对象自动进行扩展或收缩内存,保证元素之间没有缝隙
- python中,一个列表内的数据类型可以各不相同
[10,20,30,40]
['spam',2.0,5,[10,20]]
- 列表常用方法:
2.1.1 列表创建与删除
-
使用‘=’直接将一个列表赋值给变量即可创建列表对象
a_list = [] #创建一个空列表
-
使用list()函数将元组、range对象、字符串或其他类型的可迭代对象类型的数据转换为列表
x = list() #创建空列表
-
当不再使用时,使用del命令删除整个列表,如果列表对象所指向的值不再有其他对象指向,python将同时删除该值
2.1.2 列表元素的增加
- 使用‘+’运算符将元素添加到列表中(创建一个新列表,速度较慢)
aList = [3,4,5]
aList = aList + [6]
- 使用append(),原地修改列表,真正意义上在列表尾部添加元素,速度较快,不改变列表在内存中的首地址
>>> import time
>>> result = []
>>> start = time.time()
>>> start
1654653617.453265
>>> for i in range(100000):
result = result + [i]
print(len)
>>> print(len(result),','time.time() - start)
SyntaxError: invalid syntax
>>>
- 比较‘+’和‘append()’的速度差异
#使用‘+’进行添加
>>> result = []
>>> start = time.time()
>>> start
1654655999.1346374
>>> for i in range(100000):
result = result + [i]
>>> print(len(result),',',time.time() - start)
100000 , 186.77972674369812
#使用‘append()’添加元素
>>> import time
>>> result = list()
>>> start = time.time()
>>> for i in range(100000):
result.append(i)
>>> print(len(result),',',time.time()-start)
100000 , 78.57423663139343
- 列表中包含的是元素值的引用,而不是直接包含元素值。
- 如果直接修改序列变量的值,则与python普通变量的情况是意义的,而如果是通过下标来修改序列中元素的值或通过可变序列对象自身提供的方法来增加或删除元素时,序列对象在内存中的起始地址是不变的,仅仅是被改变值的元素地址发生变化,也就是所谓的“原地操作”
>>> a = [1,2,4]
>>> b = [1,2,3]
>>> a == b
False
>>> id(a) == id(b)
False
>>> id(a[0]) == id(b[0])
True
>>> a = [1,2,3]
>>> id(a)
2624030386760
>>> id(b)
2623998467400
#通过增删改对元素进行操作,序列地址不变,进行原地操作
>>> a.append(4)
>>> id(a)
2624030386760
>>> a.remove(3)
>>> id(a)
2624030386760
>>> a[0] = 5
>>> id(a)
2624030386760
- 使用列表对象extend()方法可以将另一个迭代对象的所有元素添加至该列表对象尾部,通过extend()方法来增加列表元素也不改变其内存首地址,属于原地操作
>>> a = [5,6,7,8]
>>> b = [1,2,3,4]
>>> id(b)
2624030385928
>>> b.extend(a)
>>> b
[1, 2, 3, 4, 5, 6, 7, 8]
>>> id(b)
2624030385928
- 使用insert()方法将元素添加到列表中的指定位置
- 应尽量从列表尾部进行元素的增加与删除操作
- insert()可以在列表任意位置插入元素,但由于列表的自动内存管理功能,insert()方法会涉及到插入位置之后所有元素的移动,这会影响处理速度
- 类似的还有remove()方法以及使用pop()函数弹出列表非尾部元素和使用del命令删除列表非尾部元素的情况
>>> a.insert(0,0)
>>> aimport
[0, 5, 6, 7, 8]
#对比insert函数和append函数运行效率
>>> import time
>>> def Insert():
a = []
for i in range(10000):
a.insert(0,i)
>>> def Append():
a = []
for i in range(10000):
a.append(i)
#insert()
>>> start = time.time()
>>> start
1654826751.7744946
>>> for i in range(10):
Insert()
>>> print('Insert:',time.time()-start)
Insert: 63.83978343009949
#append()
>>> start = time.time()
>>> for i in range(10):
Append()
>>> print('Append:',time.time()-start)
Append: 48.075252294540405
- 使用*来扩展列表对象,将列表与整数相乘,生成一个新列表
- 当使用*运算符将包含列表的列表重复并创建新列表时,并不创建元素的复制,而是创建已有对象的引用。因此,当修改其中一个值时,相应的引用也会被修改
>>> x = [[None] * 2] * 3
>>> x
[[None, None], [None, None], [None, None]]
>>> x[0][0] = 5
>>> x
[[5, None], [5, None], [5, None]]
>>> x = [1,2,3] * 3
>>> x
[1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> x = [[1,2,3]] * 3
>>> x
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
>>> x[0][0] = 10
>>> x
[[10, 2, 3], [10, 2, 3], [10, 2, 3]]
2.1.3 列表元素的删除
- 使用del删除指定位置元素
>>> del x[0][1]
>>> x
[[10, 3], [10, 3], [10, 3]]
- 使用列表的pop()方法删除并返回指定(默认为最后一个)位置上的元素,如果给定的索引超出了列表的范围则抛出异常
>>> a_list = list((3,5,7,9,11))
>>> a_list
[3, 5, 7, 9, 11]
>>> a_list.pop()
11
>>> a_list
[3, 5, 7, 9]
>>> a_list.pop(1)
5
>>> a_list
[3, 7, 9]
- remove()删除首次出现的指定元素,如果列表中不存在要删除的元素,则抛出异常
>>> a_list = [3,5,7,9,11]
>>> a_list.remove(7)
>>> a_list
[3, 5, 9, 11]
#列表中不存在要删除的元素,抛出异常
>>> a_list.rmeove(7)
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
a_list.rmeove(7)
AttributeError: 'list' object has no attribute 'rmeove'
#删除列表中全部的1
>>> x = [2,3,4,1,1,1,1]
>>> for i in x:
if i == 1:
x.remove(i)
>>> x
[2, 3, 4, 1, 1]
- 列表的自动内存管理功能,删除一个元素之后,python会自动对列表内存进行收缩并移动列表
#操作正常代码
#方法1
>>> for i in range(len(x) - 1,-1,-1):
if x[i] == 1:
x.remove(x[i])
>>> x
[2, 3, 4]
#方法2
>>> x = [2,3,4,1,1,1,1]
>>> for i in x[::]: #切片
if i == 1:
x.remove(i)
>>> x
[2, 3, 4]