描述
- 列表是python中很常用的一种数据类型。
- 创建一个空列表,并赋值给lists,如下:
lists = []
列表的访问与查询
- 使用下标访问
lists = ['C','Python','C++','Java','Go']
print(lists[0]) # 访问列表第一个元素
print(lists[1]) # 访问列表第二个元素
print(lists[-1]) # 访问列表最后一个元素
print(lists[-2]) # 访问列表倒数第二个元素
上面输出结果
C
Python
Go
Java
- 使用列表index()方法获取该元素首次出现的下标
lists = ['C','Python','C++','Java','Go','Python']
print(lists.index('C++')) # 输出结果:2
print(lists.index("Python")) # 输出结果:1
- 使用列表count()方法统计某个元素在列表中出现的次数
lists = ['C','Python','C++','Java','Go','Python']
print(lists.count("C"))
print(lists.count("Python"))
print(lists.count("PHP"))
上面输出结果
1
2
0
- 判断元素是否在列表内
lists = ['C','Python','C++','Java','Go','Python']
print("C" in lists) # 判断C是否在列表内,结果为True
print('PHP' in lists) # 判断PHP是否在列表内,结果为False
列表增加元素
使用(+)号运算符
>>> a_list = [1,2,3]
>>> id(a_list) # 第一次列表的内存地址
57712200
>>> a_list = a_list + [9]
>>> a_list
[1, 2, 3, 9]
>>> id(a_list) # 第二次列表的内存地址
57711304
- 使用运算符(+)号来添加元素,实际上是创建了一个新的列表,把原列表的元素和要添加的元素一起复制到新列表(在内存内重新建立的一个储存究竟)内。由于涉及大量的元素复制,开辟新内存地址,所以效率很低,一般很少用这种方法
使用列表对象的append()方法,在列表尾部追加元素
>>> a_list = [1,2,3]
>>> id(a_list) # 原内存地址
56391432
>>> a_list.append(9)
[1, 2, 3, 9]
>>> id(a_list) # 和原内存地址相同
56391432
- append()方法是在原内存地址上添加的元素,效率很高
使用重新赋值的方法
>>> a_list = [1,2,3]
>>> id(a_list) # 原内存地址
69306024
>>> a_list = [1,2,3,4,5]
>>> id(a_list) # 重新赋值后内存地址已经改变
62954120
- Python采用的是基于值的自动内存管理方式,当重新给变量赋值时,并不是修改原内存地址上的数据,而是重新开辟一个内存储存数据,并指向要赋值的变量
列表元素值的引用
- 列表中包含的是元素值的引用,而不是直接包含元素值。
- 如果是通过赋值来直接修改列表的值,则和普通变量赋值一样,是重新开辟一个内存空间
- 如果是通过下标或列表对象自身提供的方法来增加和删除元素时,列表对象在内存中的起始地址不变,仅仅是被修改的元素地址发生改变。
>>> a_list = [1,2,3]
>>> b_list = [1,2,3,4]
>>> a_list == b_list # 两个列表不是同一个对象
False
>>> id(a_list) == id(b_list) # 两个列表内存地址不同
False
>>> id(a_list[1]) == id(b_list[1]) # 两个列表内的元素2,都相同的内存地址
True
>>> id(a_list)
59471592
>>> a_list.append(5)
>>> a_list
[1, 2, 3, 5]
>>> id(a_list)
59471592
>>> a_list.remove(5)
>>> a_list
[1, 2, 3]
>>> id(a_list)
59471592
>>> a_list[0] = 6
>>> a_list
[6, 2, 3]
>>> id(a_list)
59471592
使用列表对象的extend()方法
- 方法extend()可以在列表末尾一次性追加另一个列表中的多个元素(用新列表扩展原来的列表)
- 通过extend()方法增加列表元素也不改变原列表内存地址
>>> a_list = [1,2,3]
>>> id(a_list)
17276552
>>> b_list = [4,5,6]
>>> a_list.extend(b_list)
>>> a_list
[1, 2, 3, 4, 5, 6]
>>> id(a_list)
17276552
使用列表对象insert()方法将元素添加至列表指定的任何位置。
>>> a_list = [1,2,3]
>>> a_list.insert(0,4)
>>> a_list
[4, 1, 2, 3]
- 应尽量从列表尾部进行元素的增加和删除操作
- 列表的Insert()方法可以在列表的任意位置插入元素,但由于列表的自动内存管理功能,Insert()方法会引起插入位置之后所有元素的移动,这会影响处理速度。
- 类似的还有remove()方法以及pop()弹出非列表尾部的元素,及del命令删除列表非尾部元素,这些都后引起元素的移动。
使用运算符(*)来扩展列表
- 运算符(*)是将列表与整数相乘,生成一个新的列表,新列表是原列表中元素的重复值
>>> a_list = [1,2,3]
>>> b_list = a_list
>>> id(a_list)
54493544
>>> id(b_list)
54493544
>>> a_list = a_list*3
>>> a_list
[1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> id(a_list)
54488776
>>> id(b_list)
54493544
- 当使用运算符(*)将包含列表的列表重复并创建列表时,并不是复制原列表的值,而是复制原列表中已有元素的引用。因此,当修改其中一个值时,相应的引用也会被修改。
>>> a_list = [[None]*2]*3
>>> a_list
[[None, None], [None, None], [None, None]]
>>> a_list[0][0] = 0
>>> a_list
[[0, None], [0, None], [0, None]]
>>> a_list = [[1,2,3]]*3
>>> a_list
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
>>> a_list[0][0] = 4
>>> a_list
[[4, 2, 3], [4, 2, 3], [4, 2, 3]]
列表元素的删除
使用del命令删除列表中指定位置上的元素
>>> a_list = [1,2,3]
>>> del a_list[0]
>>> a_list
[2, 3]
>>> del a_list # del可能从内存中删除整个列表
>>> a_list
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
a_list
NameError: name 'a_list' is not defined
使用列表pop()方法删除
- 方法pop()默认删除最后一个元素,并返回这个元素。
>>> a_list = [1,2,3]
>>> a_list.pop()
3
>>> a_list
[1, 2]
>>> a_list.pop(0)
1
>>> a_list
[2]
使用列表对象的remove()方法删除首次出现的指定元素
>>> a_list = [1,2,3,1]
>>> a_list.remove(1)
>>> a_list
[2, 3, 1]
- 代码编写好后必须经过反复测试,不能满足于几次测试结果正确。如下代码成功地删除了列表中的重复元素,执行结果是完全正确的。
>>> a_list = [1,2,3,1,2,5,1,3]
>>> for i in a_list:
if i == 1:
a_list.remove(i)
>>> a_list
[2, 3, 2, 5, 3]
- 然而,上面这段代码的逻辑是错误的。同样的代码,仅仅是所处理的数据发生了一点变化,结果就出错了。
>>> a_list = [1,1,2,2,3,1,1,1,]
>>> for i in a_list:
if i == 1:
a_list.remove(i)
>>> a_list
[2, 2, 3, 1, 1]
- 两组数据的本质区别在于,第一组数据中没有连续的1,而第二组数据中存在连续的1。出现这个问题的原因是列表的自动内存管理功能。
- 在删除列表元素时,Python会自动 对列表内存进行收缩并移动列表元素以保证所有元素之间没有空隙,增加列表元素时也会自动扩展内存并对元素进行移动以保证元素之间没有空隙。每当插入或删除一个元素之后,该元素位置后面所有元素的索引就都改变了。
- 正确的代码如下:
>>> a_list = [1,1,2,2,3,1,1,1,]
>>> for i in a_list[:]: # 使用切片
if i == 1:
a_list.remove(i)
>>> a_list
[2, 2, 3]
>>> a_list = [1,1,2,2,3,1,1,1,]
>>> for i in range(len(a_list)-1,-1,-1): 从后往前删除
if a_list[i] == 1:
del a_list[i]
>>> a_list
[2, 2, 3]
切片用法
- 切片适用于列表、元组、字符串、range对象等类型,但作用于列表时功能最强大。可以使用切片来截取列表中的任何部分,得到一个新列表,也可以通过切片来个性和删除列表中问他幸免于难,甚至可以通过操作切片为列表增加元素
list[a:b:c]
- a表示切片开始位置(默认为0)
- b表示切片截止(但不包含)位置(默认为列表长度)
- c表示切片的步长(默认为1),当步长省略时可以省略最后一个冒号。
- 切片操作不会因为下标越界而抛出异常,而是简单地在列表尾部截断或者返回一个空列表。
实例
>>> a_list = [1,2,3,4,5,6,7,8,9]
>>> a_list[:] # 返回包含所有元素的新列表
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a_list[::-1] # 倒序的所有元素
[9, 8, 7, 6, 5, 4, 3, 2, 1]
>>> a_list[::2] # 偶数位置,隔一个元素取值
[1, 3, 5, 7, 9]
>>> a_list[1::2] # 奇数位置,隔一个元素取值
[2, 4, 6, 8]
>>> a_list[3:] # 从下标3位置开始到最后的所有元素
[4, 5, 6, 7, 8, 9]
>>> a_list[3:6] # 下标在(3,6)之间的所有元素
[4, 5, 6]
>>> a_list[-1] # 最后一个元素
9
>>> a_list[-2] # 倒数第二个元素
8
>>> a_list[:-1] # 除最后一个元素外的所有元素
[1, 2, 3, 4, 5, 6, 7, 8]
>>> a_list[:-3:-1] # 倒序取值,从最后一位开始取值到下标为-3(不包含)
[9, 8]
>>> a_list[-3::-1] # 倒序取值,从下标为-3(包含)的位置取值到最开头
[7, 6, 5, 4, 3, 2, 1]
>>> a_list[-3:-6:-1] # 倒序取值,从下标为-3(包含)到下标为-6(不包含)
[7, 6, 5]
>>> a_list[0:100] # 前100个元素,自动截断
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a_list[100:] # 下标100之后的所有元素,自动截断
[]
>>> a_list[100] # 直接使用没有的下标访问会发生越界错误
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
a_list[100]
IndexError: list index out of range
使用切片来修改列表内容
>>> a_list = [1,2,3]
>>> a_list[len(a_list):] = [9] # 在尾部追加元素
>>> a_list
[1, 2, 3, 9]
>>> a_list[:3] = [4,5,6,7] # 覆盖下标3之前的所有元素
>>> a_list
[4, 5, 6, 7, 9]
>>> a_list[:0] = [2,3] # 在开头追加元素
>>> a_list
[2, 3, 4, 5, 6, 9]
>>> a_list[:3] = [] # 删除前3个元素
>>> a_list
[5, 6, 9]
>>> a_list = list(range(10))
>>> a_list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a_list[::2] = [0]*5 # 替换偶数位置上的元素
>>> a_list
[0, 1, 0, 3, 0, 5, 0, 7, 0, 9]
>>> a_list[::2] = [0]*3 # 切片步长不为1的时候,切片出来的元素必须与替换的元素一样多
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
a_list[::2] = [0]*3
ValueError: attempt to assign sequence of size 3 to extended slice of size 5
>>> a_list[:] = [1]*4 # 切片步长为1时,把所有元素替换成4个1
>>> a_list
[1, 1, 1, 1]
>>> a_list[2] = [2]*3 # 把下标2位置元素替换成一个包含3个2的列表
>>> a_list
[1, 1, [2, 2, 2], 1]
>>> a_list[:2] = [3]*4 # 把前两个元素替换成4个3
>>> a_list
[3, 3, 3, 3, [2, 2, 2], 1]
使用del与切片结合来删除列表元素
>>> a_list = [1,2,3,4,5,6] # 删除前3个元素
>>> del a_list[:3]
>>> a_list
[4, 5, 6]
>>> a_list = [1,2,3,4,5,6]
>>> del a_list[::2] # 删除偶数位置上的元素
>>> a_list
[2, 4, 6]
>>> a_list = [1,2,3,4,5,6]
>>> del a_list[3:5]
>>> a_list
[1, 2, 3, 6]
切片的浅复制
- 所谓浅复制,是指生成一个新的列表,并且把原列表中所有元素的引用都复制到新列表中。如果原列表中只包含整数、实数、复数等基本类型或元组、字符串这样的不可变类型的数据,一般是没有问题的。
>>> a_list = [1,2,3]
>>> b_list = a_list # 通过把a_list赋值给b_list,他们指向的是同一个内存地址
>>> b_list
[1, 2, 3]
>>> id(a_list) == id(b_list)
True # 内存地址相同
>>> b_list == a_list
True # 两个列表的元素相同
>>> b_list is a_list
True # 两个列表是同一个对象
>>> b_list[1] = 5 # 修改b_list列表,但a_list也同样被修改了
>>> a_list
[1, 5, 3]
- 由以上可知,通过赋值的方法,两个列表其实是一个对象,a_list是把内存地址赋值了给b_list
>>> a_list = [1,2,3]
>>> b_list = a_list[:] # 切片,浅复制
>>> b_list == a_list
True # 两个列表元素相同
>>> b_list is a_list
False # 两个列表不是同一个对象
>>> id(b_list) == id(a_list)
False # 两个列表内存地址不相同
>>> b_list[1] = 5 # 修改b_list,对a_list没有影响
>>> a_list
[1, 2, 3]
>>> b_list
[1, 5, 3]
- 以上的实例,列表中包含的都是不可变的数据类型,如果列表中包含可变数据类型,这种方法复制后,修改可变数据时,别一个列表也会随之改变
>>> a_list = [1,2,[3,4]]
>>> b_list = a_list[:] # 修改不可变数据,另一个列表没有影响
>>> b_list[1] = 5
>>> b_list
[1, 5, [3, 4]]
>>> a_list
[1, 2, [3, 4]]
>>> b_list[2].append(6) # 在可变数据列表内加一个6,同时另一个列表也加了一个6
>>> b_list
[1, 5, [3, 4, 6]]
>>> a_list
[1, 2, [3, 4, 6]]
列表排序
使用列表对象sort()方法对原列表进行永久性排序。
>>> a_list = [2,5,1,3,4,6,2]
>>> a_list.sort() # 默认是升序排序
>>> a_list
[1, 2, 2, 3, 4, 5, 6]
>>> a_list = [2,5,1,3,4,6,2]
>>> a_list.sort(reverse = True) # 倒序排序
>>> a_list
[6, 5, 4, 3, 2, 2, 1]
>>> a_list = [22,55555,1,333,4444]
>>> a_list.sort(key = lambda x:len(str(x))) # 按字符串的长度排序
>>> a_list
[1, 22, 333, 4444, 55555]
- 上面的–lambda x:len(str(x)) 是个匿名函数,是个固定写法,x表示列表内元素,名字可以随便取
使用内置函数sorted()对列表进行临时排序
- sorted()返回一个新的列表
>>> a_list = [2,5,1,3,4,6,2]
>>> b_list = sorted(a_list) # 临时排序,对原列表a_list没有影响
>>> b_list
[1, 2, 2, 3, 4, 5, 6]
>>> a_list
[2, 5, 1, 3, 4, 6, 2]
>>> a_list = [2,5,1,3,4,6,2]
>>> sorted(a_list,reverse = True) # 倒序排序
[6, 5, 4, 3, 2, 2, 1]
使用列表对象的reverse()方法对列表进行永久反转列表元素
- reverse()不是指按字母或数的顺序相反排序,而是反转整个列表顺序。
>>> a_list = [5,1,3,4,6,2]
>>> a_list.reverse()
>>> a_list
[2, 6, 4, 3, 1, 5]
使用内置方法reversed()对列表进行元素的临时反转
>>> a_list = [5,1,3,4,6,2]
>>> list(reversed(a_list)) # 把迭代器转换成列表
[2, 6, 4, 3, 1, 5]
>>> a_list
[5, 1, 3, 4, 6, 2]
- reversed()方法不返回列表,返回的是一个迭代器
>>> a_list = [5,1,3,4,6,2]
>>> b_list = reversed(a_list)
>>> b_list
<list_reverseiterator object at 0x03A2D7C0>
>>> for i in b_list:
print(i,end=',')
2,6,4,3,1,5,
>>> list(b_list)
[]
使用random.shuffle()方法对列表进行随机排序
>>> import random
>>> a_list = list(range(10))
>>> a_list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> random.shuffle(a_list)
>>> a_list
[3, 0, 2, 6, 5, 1, 9, 4, 7, 8]
列表推导式-列表解析
- 列表解析实际上是一个循环结构,只是形式更加简洁
>>> a_list = [value*2 for value in range(10)]
>>> a_list
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
等同于
>>> a_list = []
>>> for i in range(10):
a_list.append(i*2)
>>> a_list
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>> a_list = list(map(lambda x:x*2,range(10)))
>>> a_list
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
Python列表常用函数&方法,脚本操作符
Python表达式 | 结果 | 描述 |
---|---|---|
len(1,2,3) | 3 | 长度 |
[1,2]+[3,4] | [1,2,3,4] | 组合 |
[‘Hi’]*3 | [‘Hi’,‘Hi’,‘Hi’] | 重复 |
2 in [1,2,3] | True | 元素是否存在于列表中 |
for i in range(3):print(i,end=’,’) | 0,1,2 | 迭代 |
函数 | 描述 |
---|---|
len(list) | 列表元素个数 |
max(list) | 返回列表元素最大值 |
min(list) | 返回列表元素最小值 |
list(seq) | 将元组转换成列表 |
方法 | 描述 |
---|---|
list.append(obj) | 在列表末尾添加新的对象 |
list.count(obj) | 统计某个元素在列表中出现的次数 |
list.extend(seq) | 在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表 |
list.index(obj) | 从列表中找出某个值第一个匹配项的索引位置 |
list.insert(index,obj) | 将对象插入列表 |
list.pop(index=-1) | 移除列表中的一个元素(默认最后一个元素,并返回该元素的值 |
list.remove(obj) | 删除列表中某个值第一个匹配项 |
list.reverse() | 反向列表中元素 |
list.sort(key=None,reverse=False) | 对原列表进行排序 |
list.clear() | 清空列表 |
list.copy() | 复制列表 |