Skip to content

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 toe

7.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
1

7.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循环更清晰。