04 数据结构
前面学了列表的基本操作,这里深入讲列表的方法、列表推导式,再介绍元组、集合和字典。这四种数据结构覆盖了日常编程的大部分场景。
一、列表深入
1.1 列表方法
python
>>> fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
>>> fruits.index('apple') # 查找位置
1
>>> fruits.index('apple', 2) # 从索引2开始找
5
>>> fruits.count('apple') # 计数
2
>>> fruits.append('grape') # 末尾添加
>>> fruits.insert(0, 'mango') # 指定位置插入
>>> fruits.sort() # 原地排序
>>> fruits.reverse() # 原地反转
>>> fruits.pop() # 弹出末尾元素
'grape'
>>> fruits.pop(0) # 弹出指定位置
'mango'
>>> fruits.remove('apple') # 删除第一个匹配项
>>> fruits.clear() # 清空列表1.2 列表作为栈
append()加pop()实现后进先出:
python
>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]1.3 列表作为队列
列表做队列效率不高(pop(0)是O(n)),用collections.deque:
python
>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry")
>>> queue.popleft()
'Eric'
>>> queue.popleft()
'John'二、列表推导式
2.1 基本用法
用简洁的语法创建新列表:
python
>>> squares = [x**2 for x in range(10)]
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]等价于:
python
>>> squares = []
>>> for x in range(10):
... squares.append(x**2)2.2 带条件
python
>>> [x**2 for x in range(10) if x % 2 == 0]
[0, 4, 16, 36, 64]2.3 嵌套循环
python
>>> [(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)]等价于:
python
>>> result = []
>>> for x in [1, 2, 3]:
... for y in [3, 1, 4]:
... if x != y:
... result.append((x, y))2.4 嵌套推导式
python
>>> 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]]等价于zip(*matrix):
python
>>> list(zip(*matrix))
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]三、del语句
3.1 删除元素
python
>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
>>> a
[1, 66.25, 1234.5]
>>> del a[:]
>>> a
[]del按索引删除,remove()按值删除,pop()弹出并返回。
3.2 删除变量
python
>>> x = 42
>>> del x
>>> x
NameError: name 'x' is not defined四、元组和序列
4.1 元组基本用法
元组用圆括号,不可变:
python
>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # 元组可以嵌套
>>> u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))4.2 元组不可变
python
>>> t[0] = 88888
TypeError: 'tuple' object does not support item assignment但如果元组里有可变对象(比如列表),那个可变对象的内容可以改:
python
>>> t = ([1, 2], [3, 4])
>>> t[0].append(3)
>>> t
([1, 2, 3], [3, 4])4.3 单元素元组
单元素元组需要逗号:
python
>>> singleton = ('hello',) # 有逗号,是元组
>>> not_a_tuple = ('hello') # 没逗号,是字符串4.4 元组拆包
python
>>> t = (1, 2, 3)
>>> x, y, z = t
>>> x
1五、集合
5.1 创建集合
集合用花括号或set(),自动去重:
python
>>> basket = {'apple', 'orange', 'apple', 'banana', 'orange'}
>>> basket
{'orange', 'banana', 'apple'}
>>> # 空集合必须用set(),{}是空字典
>>> empty = set()5.2 集合运算
python
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a
{'a', 'r', 'b', 'c', 'd'}
>>> a - b # 差集
{'r', 'd', 'b'}
>>> a | b # 并集
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b # 交集
{'a', 'c'}
>>> a ^ b # 对称差集(只在一个集合中)
{'r', 'd', 'b', 'm', 'z', 'l'}5.3 集合推导式
python
>>> {x for x in 'abracadabra' if x not in 'abc'}
{'r', 'd'}六、字典
6.1 创建字典
python
>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'jack': 4098, 'sape': 4139, 'guido': 4127}
>>> tel['jack']
4098
>>> del tel['sape']
>>> list(tel.keys())
['jack', 'guido']
>>> sorted(tel.keys())
['guido', 'jack']6.2 dict()构造
python
>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'guido': 4127, 'jack': 4098}
>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'guido': 4127, 'jack': 4098}6.3 字典推导式
python
>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}6.4 遍历技巧
python
>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.items():
... print(k, v)
...
gallahad the pure
robin the brave七、遍历技巧
7.1 enumerate()带索引
python
>>> for i, v in enumerate(['tic', 'tac', 'toe']):
... print(i, v)
...
0 tic
1 tac
2 toe7.2 zip()并行遍历
python
>>> questions = ['name', 'quest', 'favorite color']
>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
... print(f'What is your {q}? It is {a}.')
...
What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favorite color? It is blue.7.3 reversed()反向遍历
python
>>> for i in reversed(range(1, 10, 2)):
... print(i)
...
9
7
5
3
17.4 in判断成员
python
>>> fruits = ['apple', 'banana', 'cherry']
>>> 'apple' in fruits
True
>>> 'grape' not in fruits
True八、总结
| 数据结构 | 特点 | 用途 |
|---|---|---|
list | 可变,有序 | 通用序列 |
tuple | 不可变,有序 | 固定数据、字典键 |
set | 可变,无序,去重 | 集合运算 |
dict | 可变,键值对 | 映射、查找 |
| 语法 | 说明 |
|---|---|
[x for x in ...] | 列表推导式 |
{x for x in ...} | 集合推导式 |
{k: v for ...} | 字典推导式 |
enumerate() | 带索引遍历 |
zip() | 并行遍历 |
reversed() | 反向遍历 |
del | 删除元素或变量 |
列表推导式比for循环更简洁,但太复杂的逻辑还是用for循环更清晰。