跳转至

6.2 数据类型进阶——元组与 range

内容梗概

本课讲解元组(tuple)与 range 两种**不可变序列**。先介绍元组的多种创建方式及单元素元组必须带逗号、复杂表达式中不能省略括号等易错点;再通过与列表对照(增加/更新/查找/其他四类操作),说明元组作为不可变序列哪些操作支持、哪些不支持。扩展讲解了可哈希(hashable)概念——不可变对象才能哈希、才能作为字典的 key。随后阐明元组最重要的实际用途:函数返回多个值,防止返回值被意外修改。最后讲解 range 也是不可变序列、支持查找和切片,以及 range 惰性生成、省内存的特性。

知识点详解

元组的创建(约 00:01)

  • 最常规方式:直接用逗号分隔,括号可省略(约 00:19)。用 type() 验证类型为 tuple。
  • 单元素元组必须带逗号(约 00:42):(1,) 才是元组,(1) 只是数字 1。
  • 在较长表达式/语句中不能省略括号(约 01:32):老师现场演示了经典错误——把元组作为函数参数时省略括号,会被拆成多个参数导致报错。
  • tuple() 构造(约 01:44):只能接收**一个**参数,且该参数须为**可迭代对象**(列表、元组本身都可以)。tuple(列表) 可把列表转为元组。

元组与列表操作的异同(约 02:42)

判断原则:凡是**修改序列本身内容**的操作(增加、更新类),元组都不支持,因为它是不可变序列。

  • 不支持:reverse(约 04:48,课堂提问互动)、append/insert/extend、pop、remove、clear、切片赋值、给某下标赋值(如 a[0] = x 报错)。
  • 支持:
  • 查找类:min、max、index、count(约 05:45);
  • 切片(约 06:04):取出的元素放进新元组,不改变原元组,完全可行;
  • 拼接:a + b 生成新元组(约 12:01 例子:教师队伍 teachers 元组想"加人",拼接另一个元组存到新变量);
  • 整体删除:del a 把整个元组变量删掉是允许的(约 08:13),报错信息是"变量不存在"而非"不能删"。
  • 没有 copy 方法(约 07:17):元组未定义 copy,但可以用完整切片 a[:] 得到一个一模一样的新元组(有点坑人,容易想当然)。

扩展:可哈希(hashable)(约 09:25)

  • 字典底层是哈希表,key 要用哈希值计算。
  • 规则:不可变对象可以哈希,可变对象不能哈希(hash() 对列表报错,对字符串、元组正常)。
  • 推论:字符串和元组可以作为字典的 key,列表不行。为 6.4 字典做铺垫。

元组的典型用途:函数返回多个值(约 13:38)

  • 用列表返回多值也能实现,但大型项目中返回值可能在别处被意外修改(如 result[0] = ...),导致后续逻辑出错且难以排查。
  • 用元组返回(return 年龄, 名字, 性别,括号可省略),任何修改尝试都会直接报错——类似 C 语言 const 的效果。
  • 惯例:函数返回多个值默认用元组;更复杂的结构化数据可用字典(结构更清晰,但可被修改)。

range(约 18:26)

  • range 本身也是**不可变序列**,支持不可变序列的所有操作:index、count、甚至切片(约 19:05 演示 range(10).index(7) 返回 7)。
  • 为什么用 range(约 20:23):range 在**迭代过程中才逐个生成数字**,不一次性占用内存。对比:生成一个上千万元素的列表约占 10 MB 内存,而 range 无论多大都占用极小空间。
  • 实践建议:实际项目中循环计数基本都用 range,不要直接循环超大列表,要有节约内存的意识。
  • 课件末尾附有一张"列表/元组/range 支持操作对照表"(约 22:38),供课后自查。

示例与演示

  • type(1,) / type(1) 验证单元素元组逗号的必要性。
  • 老师现场"翻车"演示:在函数参数位置省略元组括号导致被拆成多个参数——借此强调复杂表达式中括号不可省。
  • 课堂互动提问:"元组能用 reverse 吗?"(不能,因为属于修改内容的操作)。
  • 定义元组后演示 min/max 打印、index/count 查找、取前两个元素的切片。
  • 教师队伍例子(约 12:01):只有一个元素的元组 teachers,想加入新教师 → 拼接新元组得到新变量;演示拼接、完整切片"copy"、查找、hash()、del 整体删除(代码供课后自行运行)。
  • 函数返回多值例子(约 14:07 起):get_information() 函数假装从文件/数据库读取后 return age, name, gender;对比用列表返回被意外赋值修改、用元组返回赋值即报错。
  • range 内存对比例子(约 20:53):for i in range(10000000...)(很多个 0)配合 pass,说明同样循环用列表要占约 10 MB 而 range 几乎不占空间。

重点与难点

  • 单元素元组必须写逗号:(1,)。
  • 元组在较长表达式/函数参数中**不能省略括号**,否则被拆成多个参数。
  • tuple() 只接收一个可迭代对象参数。
  • 元组**没有** copy 方法,用 a[:] 代替;没有一切修改内容的操作,但 del 整体删除可以。
  • 可哈希规则:不可变才可哈希、才能当字典的 key;列表不可哈希。
  • 函数返回多个值**默认用元组**,防止返回值被意外修改。
  • range 是惰性序列,循环计数首选 range 而非大列表(内存意识)。

关联内容

  • 紧承 6.1 列表的操作分类框架(增加/更新/查找/其他),逐一对比元组的支持情况。
  • 可哈希概念为 6.4 字典(key 的要求)直接铺垫;哈希表概念关联后续数据结构课程。
  • 函数返回多值关联前面函数章节;"类"的概念留待面向对象章节。
  • range 关联之前的 for 循环与列表推导式(6.1 中 extend(range(20,30)) 已用到)。
  • 课件附列表/元组/range 操作对照表,建议课后自行核对。