5.1. 关于列表更多的内容
最后更新于:2022-04-01 00:47:49
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_])`
从链表的指定位置删除元素,并将其返回。如果没有指定索引,a.pop() 返回最后一个元素。元素随即从链表中被删除(方法中 _i_ 两边的方括号表示这个参数是可选的,而不是要求你输入一对方括号,你会经常在Python 库参考手册中遇到这样的标记)。
`list.index(_x_)`
返回链表中第一个值为 _x_ 的元素的索引。如果没有匹配的元素就会返回一个错误。
`list.count(_x_)`
返回 _x_ 在链表中出现的次数。
`list.sort()`
对链表中的元素就地进行排序。
`list.reverse()`
就地倒排链表中的元素。
下面这个示例演示了链表的大部分方法:
~~~
>>> 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)
>>> 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]
~~~
也许大家会发现像 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]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]
~~~
### 5.1.2\. 把链表当作队列使用
你也可以把链表当做队列使用,队列作为特定的数据结构,最先进入的元素最先释放(先进先出)。不过,列表这样用效率不高。相对来说从列表末尾添加和弹出很快;在头部插入和弹出很慢(因为,为了一个元素,要移动整个列表中的所有元素)。
要实现队列,使用 collections.deque,它为在首尾两端快速插入和删除而设计。例如:
~~~
>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry") # Terry arrives
>>> queue.append("Graham") # Graham arrives
>>> queue.popleft() # The first to arrive now leaves
'Eric'
>>> queue.popleft() # The second to arrive now leaves
'John'
>>> queue # Remaining queue in order of arrival
deque(['Michael', 'Terry', 'Graham'])
~~~
### 5.1.3\. 列表推导式
列表推导式为从序列中创建列表提供了一个简单的方法。普通的应用程式通过将一些操作应用于序列的每个成员并通过返回的元素创建列表,或者通过满足特定条件的元素创建子序列。
例如, 假设我们创建一个 squares 列表, 可以像下面方式:
~~~
>>> squares = []
>>> for x in range(10):
... squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
~~~
我们同样能够达到目的采用下面的方式:
~~~
squares = [x**2 for x in range(10)]
~~~
这也相当于 squares = map(lambda x: x**2, range(10)),但是上面的方式显得简洁以及具有可读性。
列表推导式由包含一个表达式的括号组成,表达式后面跟随一个 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 语句的顺序。
如果想要得到一个元组,必须要加上括号:
~~~
>>> vec = [-4, -2, 0, 2, 4]
>>> # create a new list with the values doubled
>>> [x*2 for x in vec]
[-8, -4, 0, 4, 8]
>>> # filter the list to exclude negative numbers
>>> [x for x in vec if x >= 0]
[0, 2, 4]
>>> # apply a function to all the elements
>>> [abs(x) for x in vec]
[4, 2, 0, 2, 4]
>>> # call a method on each element
>>> freshfruit = [' banana', ' loganberry ', 'passion fruit ']
>>> [weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']
>>> # create a list of 2-tuples like (number, square)
>>> [(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
>>> # the tuple must be parenthesized, otherwise an error is raised
>>> [x, x**2 for x in range(6)]
File "", line 1, in ?
[x, x**2 for x in range(6)]
^
SyntaxError: invalid syntax
>>> # flatten a list using a listcomp with two 'for'
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
~~~
列表推导式可使用复杂的表达式和嵌套函数:
~~~
>>> from math import pi
>>> [str(round(pi, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']
~~~
### 5.1.4\. 嵌套的列表推导式
列表推导式可以嵌套。
考虑以下的 3x4 矩阵, 一个列表中包含三个长度为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 后面的内容进行求值,所以上例就等价于:
~~~
>>> transposed = []
>>> for i in range(4):
... transposed.append([row[i] for row in matrix])
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
~~~
反过来说,如下也是一样的:
~~~
>>> transposed = []
>>> for i in range(4):
... # the following 3 lines implement the nested listcomp
... 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))
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]
~~~
更多关于本行中使用的星号的说明,参考 [_参数列表的分拆_](http://www.pythondoc.com/pythontutorial3/controlflow.html#tut-unpacking-arguments)。