跳转至

6.4 数据类型进阶——字典

内容梗概

本课是本章的重头戏,讲解字典(dict)。从字典的本质(key→value 映射、key 必须可哈希)讲起,介绍多种创建方式;再讲取值时 key 不存在会引发 KeyError 的问题及对策(in 判断、get 方法);随后介绍 pop、popitem、赋值、删除、clear、copy 等操作。后半段通过三个综合示例串联全章:序列循环进阶技巧(enumerate、zip)、集合去重与差集(签到名单)、字典排序(成绩单按分数排序,sorted + items + lambda + 字典推导式),最后给出"列表套字典"这一最常用的真实数据结构示例。

知识点详解

字典的本质(约 00:00)

  • 字典本质是**映射**(key 映射到 value),不是序列,操作不能按序列的方式分类。
  • key 必须是可哈希的值(约 00:29):字符串、整数、元组(不可变序列)都可以;value 任意(列表、元组、其他值都行)。
  • 字典的最大优势(约 04:18):取值时通过 key 就能看懂取到的是什么(如 person['name']),比列表 a[0] 的可读性好得多。

创建字典的多种方式(约 00:58)

以下方式得到的字典内容相同:

  1. dict(key1=value1, key2=value2):类似默认参数的写法,可接收多个 key=value 参数。
  2. {key1: value1, key2: value2}:花括号直接写,**最常用**的方式。
  3. dict(zip(序列1, 序列2)):用 zip(拉链)把两个等长序列配对后转字典。zip 的两个序列可可变可不可变(列表、元组均可)。
  4. dict([(k1,v1), (k2,v2)]):把列表转字典,要求每个元素是**含两个元素的元组**,前为 key 后为 value。
  5. dict(另一个字典):由已有字典生成新字典。

取值与 KeyError(约 03:41–08:14)

  • len(d) 取长度;d[key] 按键取值。
  • key 不存在时 d[key] 触发 KeyError(约 06:58),异常会导致程序中断退出——长程序/后台程序中尤其危险。
  • 对策一:先用 if key in d 判断再取值(约 08:14)。
  • 对策二:d.get(key[, default])(约 09:11):取不到时返回 None(不报错);可传 default 参数指定取不到时返回的默认值(如 d.get('weight', 100)),避免程序异常退出,简化代码。

pop 与 popitem(约 11:02)

  • d.pop(key):按键弹出,返回该 key 对应的 value。与列表不同,字典 pop 的**效率并不低**。
  • d.popitem():弹出**最后放入**的那一对(字典有顺序,后放入的在后面),返回一个 (key, value) 元组。

其他操作(约 12:24)

  • 赋值/修改:d[key] = value(改已有键或新增键值对)。
  • del d[key]:删除某个 key。
  • key in d:判断键是否存在。
  • d.clear() 清空、d.copy() 复制。
  • d.items():把 key-value 一对一对取出(返回的不是列表,但可像列表一样处理,元素是一个个元组)——配合循环与排序使用。

序列循环进阶技巧(约 13:19)

  • enumerate(约 13:50):for i, name in enumerate(列表),循环中同时拿到**下标和值**(类似 C 语言按下标循环的需求)。例:打印考试名次(下标+1)与姓名。
  • zip(约 15:18):for a, b in zip(序列1, 序列2) 同时循环两个一一对应的序列。例:学号列表与分数列表配对打印。

字典排序(约 18:10)

  • 字典**没有 sort 方法**,要用内置函数 sorted()(可对任意可迭代对象排序)。
  • 传统写法(约 19:48):
sorted_items = sorted(成绩单.items(), key=lambda x: x[1], reverse=True)
排序后 = dict(sorted_items)

即 items() 取出键值对(元组序列)→ sorted 按 lambda x: x[1](value)排序、reverse=True 让高分在前 → 再转回字典。 - Python 3.6+ 简写(约 23:10,字典推导式,本课讲 3.8):

{k: v for k, v in sorted(成绩单.items(), key=lambda x: x[1], reverse=True)}

注意:3.6 以下版本用此语法会报错。 - 潜台词:字典排序必须 items 取出 → 排序 → 转回字典,这是实际写代码中经常遇到的需求。

示例与演示

  • 创建演示(约 01:28):用 ABCD 四种方式创建相同内容的字典,print 对比(内容相同,仅顺序可能不同)。
  • 人物字典(约 03:58):{'name': '安靖', 'age': ..., 'gender': ...} 代表一个人;演示 d['name'] 取值的可读性;访问不存在的 weight 键触发 KeyError;再用 in 判断和 get、get(key, 100) 演示安全取值。
  • enumerate 名次示例:对考试名单列表,用 enumerate 同时打印名次与名字。
  • zip 配对示例:学号列表与分数列表 zip 后逐对打印。
  • 集合:签到名单差集(约 16:14):扫码签到有人重复签到,先 set 去重;set(所有学生) - set(已签到学生) 用**差集(减法)**直接求出没来的同学——非常直观。
  • 成绩单排序示例(约 18:10):随机生成 60–100 分的分数列表,与学号列表 zip 合并成字典成绩单;再用 sorted + items + lambda + reverse 排序,分别演示传统三步写法和字典推导式简写,打印排序结果(98 分排第一)。老师提到:学习委员算综测不会 Excel 公式时可以用 Python 做。
  • 列表套字典混合示例(约 25:30):最常见的真实结构——一个名单是列表,每条数据是字典。生成 10 个学生,每个字典含 name/id/score 三个 key:
  • 名字生成技巧(约 26:35):chr(ord('a') + x) 把字符转整数再加 0–9 再转回字符,得到小 a、小 b……的名字;
  • 学号顺序递增,random 随机成绩,把字典 append 进空列表;
  • 因为最外层是**列表**,可直接 sort(key=lambda x: x['score'], reverse=True) 按分数字段倒序排列,再逐个打印成绩单。

重点与难点

  • key 必须**可哈希**(不可变对象);value 任意。
  • d[key] 取不存在的键会抛 KeyError 使程序中断;用 in 判断或 get(可带 default)规避。
  • 字典有顺序(按放入先后);popitem 弹最后一对并返回元组;pop(key) 返回 value 且效率不低。
  • 字典**没有 sort 方法**,排序走 sorted(d.items(), key=..., reverse=...) 再转回字典;字典推导式简写仅 Python 3.6+ 可用。
  • enumerate 拿下标+值、zip 并行循环两个序列——循环进阶两件套。
  • {} 是空字典不是空集合(呼应 6.3)。
  • 最常用数据结构:列表套字典(列表的每个元素是一个字典)。

关联内容

  • 直接承接 6.2 的可哈希概念(元组/字符串可当 key,列表不行)与 6.3 集合(创建语法歧义、签到差集示例在此课演示)。
  • sorted 的 key=lambda 用法呼应之前匿名函数(lambda)章节;zip 呼应本课字典创建部分。
  • 提到 base64 相关例子因下周才讲而跳过;文件操作章节预告(文件按体积排序也会用字典)。
  • "列表套字典"结构为后续 JSON、数据处理、文件操作等实战内容打基础。