集合类型
引入| English | 释义 | 拼音 |
|---|---|---|
| list/lɪst/ | 列表 | liè biǎo |
| dictionary/ˈdɪkʃənəri/ | 字典 | zì diǎn |
| key/kiː/ | 键 | jiàn |
| tuple/ˈtuːpl/ | 元组 | yuán zǔ |
| set/set/ | 集合 | jí hé |
| aliasing/ˈeɪlɪəsɪŋ/ | 别名 | bié míng |
哪种饮料卖得最好?
- 咖啡店的收银机记录每一笔订单:
"tea"、"latte"、"tea"……一天 200 次。每笔订单一个变量是没用的。你需要一个能装下很多值的名字。 - Python 有四种内置的集合类型,每种适合不同的工作。选对了,程序的其余部分往往就很短。
列表按顺序保存项目
- **列表(list)**是可以修改的有序序列:
marks = [72, 55, 90, 48, 81]。位置从 0 开始数,所以marks[0]是72,而最后一项marks[-1]是81。 - 切片取出一部分:
marks[1:3]是[55, 90],从位置 1 开始,到位置 3 之前为止(不包括位置 3)。len(marks)是5。
设 s = [10, 20, 30, 40, 50],s[1:4] 是什么?
难度 1/5 · 今日首次完成可获 100 金币及少量额外奖励
位置 1 是 20(从 0 开始数),切片在位置 4 之前停止,所以取位置 1、2、3。
修改列表
marks.append(66)加到末尾;marks.remove(48)删除第一个48;marks[1] = 58替换一项。marks.sort()就地排序,返回None。想保留原列表并得到一个排好序的副本,就写sorted(marks)。
nums = [3, 1, 2]
result = nums.sort()
print(result, nums) # None [1, 2, 3]
执行 nums = [3, 1, 2] 和 nums = nums.sort() 之后,nums 是什么?
难度 1/5 · 今日首次完成可获 100 金币及少量额外奖励
sort() 就地排序并返回 None,被存进 nums 的就是这个 None。应单独写 nums.sort(),或写 nums = sorted(nums)。
字典按键查找
- **字典(dictionary)把每个键(key)**映射到一个值:
stock = {"tea": 40, "latte": 25}。stock["tea"]是40。 - 不存在的键会引发
KeyError。stock.get("mocha", 0)则返回默认值0,所以用来计数很安全。
- 数一数每种饮料各被点了几次。
- 从
tally = {}开始。对订单中的每个item,写tally[item] = tally.get(item, 0) + 1。 - 对
["tea", "flat white", "tea", "latte", "tea"],结果是{'tea': 3, 'flat white': 1, 'latte': 1}。某种饮料第一次出现得到0 + 1;之后每出现一次再加一。
计数表就是一个字典
每个键是一种饮料,每个值是它被点的次数。逐个查看键值对;查找 tally["tea"] 会直接找到它的值,不必扫描其他项。
计数循环处理 ["tea", "latte", "tea", "mocha", "tea", "latte"]。最后 tally["tea"] 是多少?
难度 2/5 · 今日首次完成可获 140 金币及少量额外奖励
"tea" 出现三次。第一次 tally.get("tea", 0) + 1 得到 1;之后每出现一次再加一。
元组与集合
- **元组(tuple)**是固定的一组值,例如一个点
p = (3, 4)。你可以拆开它,x, y = p,但p[0] = 5会引发TypeError:它不能修改。 - **集合(set)**中每个值只出现一次,没有固定顺序:
{"tea", "latte", "tea"}只有2项。用它去除重复,或快速判断某个值在不在里面。
按任务选择集合类型
- 顺序重要,或需要位置 → 列表。按名字或编号查找一个值 → 字典。
- 由几部分组成的固定组合,例如日期或坐标点 → 元组。只关心“在不在”且不要重复 → 集合。
把每项任务与最合适的集合类型配对。
难度 2/5 · 今日首次完成可获 140 金币及少量额外奖励
要顺序 → 列表;按键查找 → 字典;固定的组成部分 → 元组;不重复 → 集合。
两个名字,一个列表
b = a不会复制列表。它只是给同一个列表再贴一个名字,所以b.append(2)也会改变a显示的内容。这种共享叫做别名(aliasing)。- 需要一个独立的副本时,就复制一个:
b = a[:]或b = list(a)。

执行 a = [1, 2]、b = a、b.append(3) 之后,a 是什么?
难度 1/5 · 今日首次完成可获 100 金币及少量额外奖励
b = a 给同一个列表贴上第二个名字,所以通过 b 做的修改也能通过 a 看到。若写 b = a[:],a 会保持 [1, 2]。
不要一边遍历一边删除
- 在
for循环遍历列表时从中删除项目,会跳过一些项目:每次删除都会让后面的项目左移,而循环仍然前进到下一个位置。 - 对
m = [40, 45, 70, 30],在循环中删除所有低于 50 的分数,结果是[45, 70],45被漏掉了。应该建立一个新列表:[x for x in m if x >= 50]得到[70]。
在 for x in m: 循环里删除所有低于 50 的项,总是只留下 50 及以上的项。
难度 1/5 · 今日首次完成可获 100 金币及少量额外奖励
每次删除都让后面的项左移,于是循环跳过一项。[40, 45, 70, 30] 最后变成 [45, 70]。应写 [x for x in m if x >= 50] 建立新列表。
容易丢分的地方
- 从 1 开始数。 第一项是
[0];最后一项是[len(x) - 1]或[-1]。 x = x.sort()。sort()返回None,x就丢了。单独调用x.sort(),或使用sorted(x)。- 对可能不存在的键用
d[key]。 使用d.get(key, default),或先测试if key in d:。 - 以为
b = a会复制。 它是共享;需要两个列表时用a[:]复制。
d = {"tea": 2}。哪些行运行时不会引发错误?选出所有正确项。
难度 2/5 · 今日首次完成可获 140 金币及少量额外奖励
用 d["mocha"] 读取不存在的键会引发 KeyError。.get 返回默认值,in 返回 False,给新键赋值则会直接添加它。
你掌握了
- 列表:有序、可修改,位置从 0 开始,切片
[a:b]在b之前停止。字典:键 → 值,.get(key, default)不会报错。 - 元组:可以拆开的固定组合。集合:值不重复,判断成员很快。
b = a共享同一个列表(别名);用a[:]复制。不要从正在遍历的列表中删除项目,应建立新列表。