本章详细讨论一些之前学过的内容,同样也添加了一些新内容。
5.1关于列表更多的内容
Python的列表数据类型包含更多的方法。这里是所有的列表对象方法:
list.append(x)
把一个元素添加到列表的结尾,相当于a[len(a)] = [x]
list.extend(L)
将一个给定列表中的所有元素都添加到另一个列表中,相当于a[len(a):] = L
list.insert(i, x)
在指定位置插入一个元素。第一个参数是准备插入的元素的索引,例如a.insert(0,x)
会插入到整个列表之前,而a.insert(len(a), x)
相当于a.append(x)
。
list.remove(x)
删除列表中值为x的第一个元素。如果没有这样的元素,会返回一个错误。
list.pop([i])
从列表的指定位置删除元素,并将其返回。如果没有指定索引,会返回最后一个元素,也就是-1位置上的元素。元素随即从列表中被删除(方法中i两边的方括号表示这个参数是可选的,而不是要求你输入这个括号,这是Python库参考手册中常用的标记。)
list.clear()
从列表中删除所有元素,相当于del a[:]
。
list.index(x)
返回列表中第一个值为x的元素的索引。如果没有匹配的元素会返回一个错误。
list.count(x)
返回x在列表中出现的次数。
list.sort()
对列表中的元素就地进行排序。意味着排序后会修改这个列表本身。
list.reverse()
就地倒排列表中的元素。
list.copy()
返回列表的一个浅拷贝。等同于list[:]。
下面这个示例演示了列表的大部分方法:
a = [66.25, 333, 333, 1, 1234.5]
print(a.count(333), a.count(66.25), a.count('x'))
2 1 0
a.insert(2, -1)
a.append(333)
a
[66.25, 333, -1, 333, 1, 1234.5, 333]
a.index(333)
1
a.remove(333) #会删除第一个遇到的333
a
[66.25, -1, 333, 1, 1234.5, 333]
a.reverse() #把顺序整个倒过来
a
[333, 1234.5, 1, 333, -1, 66.25]
a.sort() #从小往大排
a
[-1, 1, 66.25, 333, 333, 1234.5]
a.sort(key = lambda x: -x) #复习一下lambda函数
a
[1234.5, 333, 333, 66.25, 1, -1]
a.pop() #删除最后一个元素,并返回
-1
a #可以看到-1不在了
[1234.5, 333, 333, 66.25, 1]
也许大家会发现像insert,remove或者sort这些修改列表的方法没有打印返回值-其实它们返回的是None。在python中对穗游客变得数据类型这是统一的设计原则。
5.1.1.把列表当做堆栈使用
列表的方法使得列表可以很方便的做为一个堆栈来使用,堆栈做为特定的数据结构,最先进入的元素最后一个被释放(后进先出)。用append()
方法可以把一个元素添加到堆栈顶。用不指定索引的pop()
方法可以把一个元素从堆栈顶释放出来。例如:
stack = [3, 4, 5]
stack.append(6)
stack.append(7)
stack
[3, 4, 5, 6, 7]
stack.pop()
7
stack
[3, 4, 5, 6]
5.1.2.把列表当做队列使用
你也可以把列表当做队列使用,队列作为特定的数据结构,最先进入的元素最先释放(先进先出)。不过,列表这样使用效率不高。相对来说,从列表末尾添加和弹出很快,在头部插入和弹出很慢(应为,为了一个元素,要移动整个列表中的所有元素)。
要实现队列,使用collections.deque,它为在首尾两端快速插入和删除而设计,例如:
from collections import deque
queue = deque(['Eric', 'John', 'Michael'])
queue.append('Terry') #插入Terry
queue.append('Graham') #插入Graham
queue.popleft() #第一个插入的第一个离开
queue.popleft() #第二个插入的第二个离开
queue #剩余的队列,顺序与插入的顺序相同
deque(['Michael', 'Terry', 'Graham'])
5.1.3.列表推导式
列表推导式为创建列表提供了一个简单的方法。普通的创建列表的方法是通过将一些操作生成列表的每个成员并通过这些返回的成员来创建列表,或者通过满足特定条件的元素创建列表。
例如,假设我们创建一个squares列表,可以像下面方式:
squares = []
for x in range(10):
squares.append(x ** 2)
print(squares)
print(x)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
9
注意这个for循环中的被创建的名为x
的变量在循环完毕后依然存在,这不是我们想看到的,我们只想要生成一个列表。使用如下方法,我们可以生成squares的元素同时不会产生任何的副作用。
squares = list(map(lambda x: x**2, range(10)))
squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
甚至可以写的更简洁:
squares = [x**2 for x in range(10)]
squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
列表推导式由一个包含表达式的括号组成,表达式后面跟随一个for子句,之后可以有零或多个for或if子句。得到的结果是一个列表,由表达式依据其后面的for和if子句计算而来的结果构成。
例如,如下的列表推导式生成的由两个列表中不相等的元素生成的元组而组成的列表:
[(x,y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
等同于:
combs = []
for x in [1, 2, 3]:
for y in [3, 1, 4]:
if x != y:
combs.append((x, y))
combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
值得注意的是在上面两个方法中的for和if语句的顺序。
如果想得到一个元组(例如上面例子的(x,y)
),就必须要加上括号:
vec = [-4, -2, 0, 2, 4]
#创建一个得到原列表内的元素值平方的列表
print([x*2 for x in vec])
#过滤掉负数
print([x for x in vec if x >= 0])
# 对vec列表中所有元素进行函数调用
print([abs(x) for x in vec])
# 对一个列表中每一个元素使用方法
freshfruit = [' banana', 'loganberry ', ' passion fruit ']
print([weapon.strip() for weapon in freshfruit])
#创建由包含两个元素的元组组成的列表,形式如下(数字,平方)
print([(x, x ** 2) for x in range(4)])
#创建一个列表,用两个for和一个if
print([x for i in range(6) for x in [1,3,5,7,9] if x==i])
#创建一个列表,用两个for
vec = [[1,2,3], [4,5,6], [7,8,9]]
print([num for three_num in vec for num in three_num])
[-8, -4, 0, 4, 8]
[0, 2, 4]
[4, 2, 0, 2, 4]
['banana', 'loganberry', 'passion fruit']
[(0, 0), (1, 1), (2, 4), (3, 9)]
[1, 3, 5]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
5.1.4.嵌套的列表推导式
列表解析中的第一个表达式可以是任何表达式,包括列表解析。
考虑下面由三个长度为4的列表组成的3×4矩阵:
matrix = [[1,2,3,4],
[5,6,7,8],
[9,10,11,12],]
现在,如果你想交换行和列,可以用嵌套的列表推导式:
[[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
像之前看到的,嵌套的列表推导式是对for后面的内容进行求值,所以上例就等价于:
transposes = []
for i in range(4):
transposes.append([row[i] for row in matrix])
transposes
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
反过来说,如下也是一样的:
transposed = []
for i in range(4):
transposed_row = []
for row in matrix:
transposed_row.append(row[i])
transposed.append(transposed_row)
transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
在实际中,你应该更喜欢使用内置函数组成复杂流程语句。对这种情况zip()
将会做的更好:
list(zip(*matrix)) #这个*号,是函数中参数列表的拆分,参见上一章4.7.4
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]