《象》曰“君子以同而异”。对于Python中不同的序列类型而言,有很多方法是通用的,而不同类型的序列又有一些特有的方法或支持某些特有的运算符。常用的列表对象方法如下表所示。此外,Python的很多内置函数和命令也可以对列表和其他序列对象进行操作。后面章节中将通过一些案例陆续进行介绍。
方法 | 说明 |
lst.append(x) | 将元素x添加至列表lst尾部 |
lst.extend(L) | 将列表L中所有元素添加至列表lst尾部 |
lst.insert(index,x) | 在列表lst指定位置index处添加元素 x,该位置后面的所有元素后移一个位置 |
lst.remove(x) | 在列表lst中删除首次出现的指定元素,该元素之后的所有元素前移一个位置 |
lst.pop([index]) | 删除并返回列表lst中下标为index(默认为-1)的元素 |
lst.clear() | 删除列表lst中的所有元素,但保留列表对象 |
lst.index(x) | 返回列表lst中第一个值为x的元素的下标,若不存在值为x的元素则抛出异常 |
lst.count(x) | 返回指定元素x在列表lst中的出现次数 |
lst.reverse() | 对列表所有元素进行排序 |
lst.sort(key=None,reverse=False) | 对列表lst中的元素进行排序,key用来指定排序依据(是自定义函数名),reverse决定 升序(False)还是降序(True) |
lst.copy() | 返回列表lst的浅复制,浅复制的介绍参考2.1.4节 |
练习篇:
1 append()、insert()、extend()
1 >>> # 这3个方法都可以用于向列表对象中添加元素,其中,append()用于向列表尾部追加一个元素,insert()用于向列表任意指定位置插入一个元素,
extend()用于将另一个列表中的所有元素追加至当前列表的尾部,这3个方法都属于原地操作,不影响列表对象在内存中的起始地址
2 >>>
3 >>> x = [1,2,3]
4 >>> id(x) #查看对象的内存地址
5 57767112
6 >>>
7 >>> x.append(4) #在列表尾部追加元素
8 >>>
9 >>> x
10 [1, 2, 3, 4]
11 >>>
12 >>> x.insert(0,0) #在列表指定位置插入元素
13 >>>
14 >>> x
15 [0, 1, 2, 3, 4]
16 >>>
17 >>> x.extend([5,6,7]) #在列表尾部追加多个元素
18 >>>
19 >>> x
20 [0, 1, 2, 3, 4, 5, 6, 7]
21 >>>
22 >>> id(x)
23 57767112
24 >>>
25 >>>
26 >>> #另外,运算符+和*也可以实现列表增加元素的目的,但这两个运算符不属于原地操作,而是返回新列表。
27 >>>
28 >>> x = [1,2,3,4]
29 >>> id(x)
30 54919496
31 >>>
32 >>> x = x + [4] #连接2个列表
33 >>> x
34 [1, 2, 3, 4, 4]
35 >>>
36 >>> id(x) #内存地址
37 58536904
38 >>>
39 >>> x = x * 2 #列表元素重复
40 >>> x
41 [1, 2, 3, 4, 4, 1, 2, 3, 4, 4]
42 >>>
43 >>> id(x)
44 54924936
45 >>>
2 pop()、remover()、clear()
1 >>> #这3个方法用于删除列表中的元素,其中,pop()用于删除并返回指定位置(默认是最后一个)上的元素,remove()用于删除列表中第一个值与指定值相等的元素,
clear()用于清空列表,这3个方法属于原地操作,不影响列表对象的内存地址。另外,也可以使用del命令删除列表中指定位置的元素,也属于原地操作。
2
3 >>> x = [1,2,3,4,5,6,7]
4 >>>
5 >>> x.pop() #弹出并返回尾部元素
6 7
7 >>> x.pop(0) #弹出并返回指定位置的元素
8 1
9 >>>
10 >>> x.clear() #删除列表所有元素
11 >>>
12 >>> x
13 []
14 >>>
15 >>> x = [1,2,1,1,2]
16 >>>
17 >>>
18 >>> x.remove(2) #删除第一个值为2的元素
19 >>> x
20 [1, 1, 1, 2]
21 >>>
22 >>>
23 >>> del x[3] #删除指定位置上的元素
24 >>> x
25 [1, 1, 1]
26 >>>
小提示:在列表中间位置插入或删除元素是,会影响该位置后面所有元素的下标,要尽量避免在列表中间位置进行元素怒的插入和删除操作。
3 count()、index()
1 >>> #列表方法 count() 用于返回列表中指定元素出现的次数,
2 #index()用于返回指定元素在列表中首次出现的位置,如果该元素不在列表中则抛出异常。除此之外,
3 #成员测试运算符in也可以测试测试列表中是否存在某个元素
4 >>>
5 >>> x = [1,2,2,3,3,3,4,4,4,4]
6 >>>
7 >>> x.count(3) #元素 3 在列表 x 中出现的次数
8 3
9 >>>
10 >>> x.count(5) #统计元素 5 在列表中出现的次数,返回0次,说明列表中没有这个元素值
11 0
12 >>>
13 >>> x.index(2) #元素 2 在列表 x 中首次出现的索引
14 1
15 >>>
16 >>> x.index(4)
17 6
18 >>>
19 >>> x.index(5) #列表x中没有元素5,抛出异常
20 Traceback (most recent call last):
21 File "<pyshell#92>", line 1, in <module>
22 x.index(5) #列表x中没有元素5,抛出异常
23 ValueError: 5 is not in list
24 >>>
25 >>> 5 in x #元素5不是列表x的元素
26 False
27 >>>
28 >>> 3 in x #元素3是列表的元素
29 True
30 >>>
4 sort()、reverse()
1 #一提到排序,有其他语言编程经验的渎职脑海里立刻会涌现出冒泡法、选择法、插入法、快速排序等名词,以及繁琐的代码和让人头疼的循环边界条件,
而逆序也涉及大量元素的交换操作和循环边界的控制。虽然学习和掌握各种排序算法的过程会锻炼我们演进的逻辑思维能力,但实际运用中我们更希望简单一些。
试想,如果只需要把排序的要求明确地告诉计算机,计算机就能立刻满足我们的要求,那将会是一种什么样的体验!至于计算机内部是如何实现排序的,谁会关心!
2
3 #列表对象的sort()方法用于按照指定的规则对所有元素怒进行排序,默认规则是直接比较元素怒大小;reverse()方法用于将列表所有元素逆序排列。
4
5 >>> x = list(range(11)) #包含11个整数的列表
6 >>>
7 >>> import random
8 >>> random.shuffle(x) #打乱列表的顺序
9 >>>
10 >>> x
11 [8, 6, 3, 10, 4, 7, 2, 1, 9, 0, 5]
12 >>>
13 >>> x.sort(key = lambda item:len(str(item)),reverse=True) #按指定规则进行排序
14 >>>
15 >>> x
16 [10, 8, 6, 3, 4, 7, 2, 1, 9, 0, 5]
17 >>>
18 >>> x.reverse() #逆序
19 >>>
20 >>> x
21 [5, 0, 9, 1, 2, 7, 4, 3, 6, 8, 10]
22 >>>
23 >>> x.sort(key=str) #按转换为字符串后的大小排序
24 >>> x
25 [0, 1, 10, 2, 3, 4, 5, 6, 7, 8, 9]
26 >>>
27 >>>
28 >>> x.sort() #按默认规则排序
29 >>> x
30 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
31 >>>
32 >>>
33
34
35
36 #需要注意的是,列表独享的sort()和reverse()是对列表进行原地排序(in-place sorting)和逆序。所谓”原地“,意思是用处理后的数据替换原来的数据,
列表中元素原来的顺序全部丢失。如果原来的顺序不想丢失,可以使用内置函数sorted()和reversed()分别得到新的列表和迭代对象。其中,
内置函数sorted()返回新列表,内置函数reversed()返回一个逆序排列后的迭代对象,这两个函数都原列表做任何修改。
37
38 >>> x = list(range(11))
39 >>> import random
40 >>> random.shuffle(x) #打乱顺序
41 >>>
42 >>> x
43 [3, 10, 5, 1, 4, 9, 0, 6, 7, 2, 8]
44
45 >>> sorted(x) #以默认规则排序
46 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
47 >>>
48 >>> sorted(x,key = lambda item : len(str(item)),reverse=True) #以指定规则排序
49 [10, 3, 5, 1, 4, 9, 0, 6, 7, 2, 8]
50 >>>
51 >>> sorted(x,key=str)
52 [0, 1, 10, 2, 3, 4, 5, 6, 7, 8, 9]
53 >>>
54 >>> x
55 [3, 10, 5, 1, 4, 9, 0, 6, 7, 2, 8]
56 >>>
57 >>>
58 >>> reversed(x) #逆序
59 <list_reverseiterator object at 0x000000000349B588> #这是一个迭代器对象,后边再介绍什么是可迭代对象和迭代器对象吧
60 >>>
61 >>> list(reversed(x))
62 [8, 2, 7, 6, 0, 9, 4, 1, 5, 10, 3]
63 >>>
64
65
66
67 拓展知识:
68 排序方法的key参数。充分利用列表对象的sort()方法和内置函数sorted()的key参数,可以实现更加复杂的排序,以内置函数sorted()为例:
69
70
71 >>> #创建一个嵌套列表,两层,元素的访问方式就像二位数组
72 >>> gameresult=[
73 ['Bob', 95.0,'A'],
74 ['Alan', 86.0,'C'],
75 ['Mandy', 83.5,'A'],
76 ['Rob', 89.3,'E']]
77 >>>
78 >>> from operator import itemgetter
79 >>>
80 >>> sorted(gameresult,key=itemgetter(2)) #按字列表第三个元素进行升序排序
81
82 [['Bob', 95.0, 'A'], ['Mandy', 83.5, 'A'], ['Alan', 86.0, 'C'], ['Rob', 89.3, 'E']]
83 >>>
84
85 >>> sorted(gameresult,key=itemgetter(2,0)) #按第三个元素升序,然后按第一个元素升序排序
86 [['Bob', 95.0, 'A'], ['Mandy', 83.5, 'A'], ['Alan', 86.0, 'C'], ['Rob', 89.3, 'E']]
87 >>>
88
89 >>> sorted(gameresult,key=itemgetter(2,0),reverse=True)
90 [['Rob', 89.3, 'E'], ['Alan', 86.0, 'C'], ['Mandy', 83.5, 'A'], ['Bob', 95.0, 'A']]
91 >>>
92 >>>
93 >>> list1 = ["what","I'm","sorting","by"] #以一个列表内容为依据
94 >>>
95 >>> list2 = ["something","else","to","sort"] #对另一个列表内容进行排序
96 >>>
97 >>> pairs = zip(list1,list2) #把两个列表中的对应位置元素配对
98 >>>
99 >>> pairs
100 <zip object at 0x00000000037D3C88>
101
102 >>> list(pairs)
103 [('what', 'something'), ("I'm", 'else'), ('sorting', 'to'), ('by', 'sort')]
104 >>>
105 >>>
106 >>> [item[1] for item in sorted(pairs,key=lambda x:x[0],reverse=True)]
107 ['something', 'to', 'sort', 'else']
108 >>>
109 >>>
110 >>> x = [
111 [1,2,3],
112 [2,1,4],
113 [2,2,1]]
114 >>>
115 >>> sorted(x,key=lambda item:(item[1],-item[2])) #以第二个元素升序、第三个元素怒降序排序
116 [[2, 1, 4], [1, 2, 3], [2, 2, 1]]
117 >>>
118 >>>
119 >>> x = ['aaaa','bc','d','b','ba']
120 >>> sorted(x,key=lambda item:(len(item),item)) #先按长度排序,长度一样的正常排序
121 ['b', 'd', 'ba', 'bc', 'aaaa']
122 >>>
5 内置函数对列表的操作
1 #除了列表对象自身方法之外,很多Python内置函数也可以对列表进行操作。例如,
2 #max()、min() 函数用于返回列表中所有元素的最大值和最小值
3 #sum()函数用于返回数值型列表中所有元素之和,
4 #len()函数用于返回列表中元素个数,
5 #zip()函数用于将多个列表中元素重新组合为元组并返回包含这些元素的zip对象,
6 #enumerate()函数返回包含若干下标和值的迭代对象
7
8
9 >>> x = list(range(11)) #生成列表
10 >>>
11 >>> import random
12 >>>
13 >>> random.shuffle(x) #打乱列表中元素顺序
14 >>>
15 >>> x
16 [10, 7, 9, 1, 5, 0, 2, 4, 3, 8, 6]
17 >>>
18 >>> max(x) #返回最大值
19 10
20
21 >>> max(x,key = str) #按指定规则返回最大值
22 9
23
24 >>> min(x)
25 0
26 >>>
27 >>> sum(x) #所有元素之和
28 55
29 >>>
30 >>> len(x) #列表元素个数
31 11
32 >>>
33 >>> list(zip(x,[1]*11)) #多列表元素重新组合
34
35 [(10, 1), (7, 1), (9, 1), (1, 1), (5, 1), (0, 1), (2, 1), (4, 1), (3, 1), (8, 1), (6, 1)]
36 >>>
37 >>> list(zip(range(1,4)) #zip()函数也可以用于一个序列或迭代对象
38 )
39 [(1,), (2,), (3,)]
40 >>>
41 >>>
42 >>> list(zip(['a','b','c'],[1,2])) #如果两个列表不等长,以短的为准
43 [('a', 1), ('b', 2)]
44 >>>
45 >>> x
46 [10, 7, 9, 1, 5, 0, 2, 4, 3, 8, 6]
47
48 >>> enumerate(x) #枚举列表元素,返回enumerate对象
49 <enumerate object at 0x00000000037D1900>
50 >>>
51 >>> list(enumerate(x))
52 [(0, 10), (1, 7), (2, 9), (3, 1), (4, 5), (5, 0), (6, 2), (7, 4), (8, 3), (9, 8), (10, 6)]
53 >>>
1 #在Python中,map()、reduce()、filter()是函数式编程的重要体现形式。内置阿寒湖map()可以将一个函数作用(或映射)到序列或迭代器对象的每个每个元素上,
并返回一个map对象作为结果,其中,每个元素是原序列中元素经过该函数处理后的结果,不对原序列或迭代器对象做任何修改。下面的代码用到后面章节的只是,
大家如果看不懂的话也不要焦虑,一本好书就是需要前前后后反复翻看很多遍才能融会贯通的,正所谓“书读百遍其义自见”。
2
3 #===================================map()函数
4
5 >>> list(map(str,range(5))) #转换为字符串
6 ['0', '1', '2', '3', '4']
7 >>>
8
9 >>> def add5(v): #单参数函数
10 return v + 5
11
12 >>>
13 >>> list(map(add5,range(10))) #把但参数函数映射到一个序列的所有元素
14 [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
15 >>>
16 >>>
17 >>> def add(x,y): #可以接受2个参数的函数
18 return x + y
19
20 >>>
21 >>> list(map(add,range(5),range(5,10))) #可以接受两个参数的函数
22 [5, 7, 9, 11, 13]
23 >>>
24 >>>
25 >>> list(map(lambda x,y:x + y,range(5),range(10))) #把双参数映射到两个序列上,得到结果的元素数以序列元素少的序列为准
26 [0, 2, 4, 6, 8]
27 >>>
28 >>> list(map(lambda x,y:x + y,range(5),range(5,10)))
29 [5, 7, 9, 11, 13]
30 >>>
31 >>>
32 >>> [add(x,y) for x,y in zip(range(5),range(5,10))]
33 [5, 7, 9, 11, 13]
34 >>>
35 >>>
36
37
38 #===================================reduce()函数
39 #标准库functools中的函数reduce(0可以将一个接受2个参数的函数以累积的方式从左到右依次作用到一个序列或迭代器对象的所有元素上。
40
41 >>> def add(x,y): #可以接受2个参数的函数
42 return x + y
43
44 >>> from functools import reduce
45 >>>
46 >>> seq = [1,2,3,4,5,6,7,8,9]
47 >>>
48 >>>
49 >>> reduce(add,range(10))
50 45
51 >>>
52 >>>
53 >>> reduce(lambda x,y:x + y,range(10))
54 45
55
56
57 #===================================filter()函数
58 #内置函数filter()将一个但参数函数作用到一个序列上,返回该序列中使得该函数返回值为True的那些元素组成的filter对象,如果指定函数为None,则返回序列中等价于True的元素。
59
60 >>> seq = ['foo','x41','?!','***']
61
62 >>> def func(x):
63 return x.isalnum() #测试是否为字母或数字
64
65 >>>
66 >>> filter(func,seq) #返回filter对象
67 <filter object at 0x00000000037D9550>
68 >>>
69 >>> list(filter(func,seq)) #把filter对象转换位列表
70 ['foo', 'x41']
71 >>>
72 >>> seq #以上操作并不对原列表做任何修改
73 ['foo', 'x41', '?!', '***']
74 >>>
75 >>> [x for x in seq if x.isalnum()] #用列表推导式实现相同功能
76 ['foo', 'x41']
77 >>>
78 >>> list(filter(lambda x:x.isalnum(),seq)) #使用lambda表达式实现相同功能
79 ['foo', 'x41']
80 >>>
81 >>>
82 >>> list(filter(None,[1,2,3,0,0,4,0,5])) #指定函数为None ,还记得哪些Python对象等价于True吗?这里就用到了
83 [1, 2, 3, 4, 5]
84 >>>
85
86
87
88 #==============================小提示
89 #max()、min()、len()、zip()\enumerate()、sorted()、reversed()、map()等内置函数以及成员测试运算符in也适用于列表对象,以及元组,字符串。
拓展知识:使用列表模拟向量运算
1 #使用列表模拟向量运算。Python列表支持与申述的乘法运算,表示列表元素进行重复并生成新列表,不对原列表进行任何修改。
2
3 >>> [1,2,3] * 3
4 [1, 2, 3, 1, 2, 3, 1, 2, 3]
5
6 #Python列表不支持与整数的加、减、除运算,也不支持列表之间的加、减、除操作。列表之间的加法运算表示列表元素的合并,生成新列表,而不是向量意义的加法。
7
8 >>> [1,2,3] + [4,5,6]
9 [1, 2, 3, 4, 5, 6]
10
11 #然而,向量运算经常涉及这样的操作,例如,向量所有分量同时加、减、乘、除统一个数,或者向量之间的加、减、乘运算,
12 #Python列表对象本身不支持这样的操作,不过可以借助内置函数和标准库operator中的方法来实现,或者使用扩展库numpy实现更加强大的功能。
13
14
15 >>> import random
16 >>> x = [random.randint(1,100) for i in range(10)] #生成10个[1,100)区间内的随机数
17 >>> x
18 [74, 87, 40, 46, 9, 75, 88, 25, 34, 53]
19 >>>
20 >>> list(map(lambda i:i + 5, x)) #列表x的所有元素值同时加5
21 [79, 92, 45, 51, 14, 80, 93, 30, 39, 58]
22 >>>
23 >>> x = [random.randint(1,10) for i in range(10)] #生成10个[1,10)区间内的随机数
24 >>> x
25 [9, 5, 4, 5, 8, 9, 1, 4, 1, 8]
26 >>>
27 >>> y = [random.randint(1,10) for i in range(10)]
28 >>> y
29 [7, 4, 7, 9, 5, 4, 10, 4, 4, 1]
30 >>>
31 >>>
32 >>> import operator
33 >>>
34 >>> m = map(operator.mul,x,y)
35
36 >>> m
37 <map object at 0x00000000037D9710>
38
39 >>> list(m)
40 [63, 20, 28, 45, 40, 36, 10, 16, 4, 8]
41 >>>
42 >>>
43 >>> m = map(operator.mul,x,y)
44 >>> sum(m)
45 270
46 >>>
47 >>>
48 >>>
49 >>> sum((i * j for i,j in zip(x,y))) #计算向量内积
50 270
51 >>>
52
53 >>>sum((i * j for i,j inzip(x,y)) #使用内置函数计算向量内积
54 270
55
56 >>> list(map(operator.add,x,y)) #两个等长的向量对应元素相加
57 [16, 9, 11, 14, 13, 13, 11, 8, 5, 9]
58 >>>
59 >>> list(map(lambda i,j:i + j,x,y)) #使用lambda表达式实现相同效果
60 [16, 9, 11, 14, 13, 13, 11, 8, 5, 9]
61 >>>
总结:
列表可以说是Python功能最强大的数据类型之一,提供了大量的方法支持各种操作,同时很多Python内置函数也可以作用于列表。看起来非常复杂的样子,确实不太好记。当暂时还是菜鸟的你看到Python高手运指如飞,行云流水一样完成一个又一个功能,然后一脸崇拜地问高手如何才能记得住那么复杂的东西,高手可能会淡淡地给你一个令人抓狂的答案“无他,唯手熟尔”。是的,高手没有忽悠你,要想精通,就要多练,多动手才能真正理解,才能出神入化。不要值羡慕高手编写代码是的潇洒和写意,更要看到高手背后的努力和拼搏。