Python3 元组超详细新手教程
元组(tuple)和列表非常像,核心区别只有一个:列表是可变的,元组是不可变的。你可以把元组理解成 “一旦创建就不能修改的列表”,它是 Python 中非常基础的有序容器,很多底层语法都依赖元组实现。本文从零讲起,所有代码都可直接复制运行。
一、什么是元组?核心特点
1. 基础定义
元组用英文小括号 () 包裹,内部多个元素用英文逗号 , 分隔,元素可以是数字、字符串、列表等任意类型。
# 定义一个元组t = ("苹果", "香蕉", "橙子")print(t)print(type(t)) # 查看类型:<class 'tuple'>
2. 核心特点(新手必记,和列表对比)
简单总结:如果一组数据创建后就不需要修改,用元组更安全、更高效;需要频繁修改数据,就用列表。
二、元组的 4 种定义方式
1. 标准定义(小括号 + 逗号)
最常用的写法:
# 存储多个元素fruits = ("苹果", "香蕉", "橙子", "西瓜")# 混合类型mix_tuple = (100, "Python", True, 3.14)print(fruits)print(mix_tuple)
2. 空元组
没有任何元素的元组,用 () 直接定义:
empty_tuple = ()print(empty_tuple) # ()print(len(empty_tuple)) # 长度0
3. ⚠️ 单个元素的元组(新手头号大坑)
只有 1 个元素的元组,必须在元素后面加英文逗号,否则括号会被当成普通括号,不是元组。
# ❌ 错误写法:不是元组,是整数t1 = (10)print(type(t1)) # <class 'int'># ✅ 正确写法:加逗号才是元组t2 = (10,)print(type(t2)) # <class 'tuple'>
为什么会这样?因为小括号在 Python 里还可以表示数学运算的优先级,比如 (10+5),所以单个元素加括号会被当成普通数值。只有加了逗号,Python 才会识别为元组。
4. 省略括号的隐式定义
元组可以省略小括号,直接用逗号分隔多个值,Python 会自动识别为元组,这种写法叫「元组打包」。
# 省略括号,本质还是元组t = 10, 20, 30print(t)print(type(t)) # <class 'tuple'>
这种写法非常常用,比如函数返回多个值、变量交换,底层都是用的隐式元组。
三、元组的索引与切片
元组是有序容器,索引规则、切片规则和列表完全一致,唯一区别是:只能通过索引取值,不能通过索引修改值。
1. 索引取值
t = ("a", "b", "c", "d", "e")# 正向索引:0 1 2 3 4# 反向索引:-5-4-3-2-1# 正向取print(t[0]) # aprint(t[2]) # c# 反向取print(t[-1]) # eprint(t[-2]) # d
2. 切片截取子元组
切片规则和列表完全一样:[起始:结束:步长],左闭右开,返回新元组。
t = (10, 20, 30, 40, 50, 60)# 截取索引1到4print(t[1:4]) # (20, 30, 40)# 省略开头print(t[:3]) # (10, 20, 30)# 省略结尾print(t[2:]) # (30, 40, 50, 60)# 反转元组print(t[::-1]) # (60, 50, 40, 30, 20, 10)
❌ 重点:不能通过索引修改元素
这是元组和列表最核心的区别,尝试修改会直接报错:
t = ("苹果", "香蕉", "橙子")# 报错:TypeError: 'tuple' object does not support item assignmentt[0] = "西瓜"
四、元组支持的通用操作
因为不可变,元组没有 append/remove/pop/sort 这类修改方法,只有查询、统计类的通用操作。
1. 基础运算
和列表、字符串规则一致,运算后生成新元组,原元组不变。
t1 = (1, 2)t2 = (3, 4)# 拼接 +print(t1 + t2) # (1, 2, 3, 4)# 重复 *print(t1 * 3) # (1, 2, 1, 2, 1, 2)
2. 成员运算 in /not in
判断元素是否在元组中:
t = ("苹果", "香蕉", "橙子")print("香蕉" in t) # Trueprint("西瓜" in t) # False
3. 长度、最值、求和
和列表用法完全一样:
t = (10, 20, 30, 40)print(len(t)) # 4 元素个数print(max(t)) # 40 最大值print(min(t)) # 10 最小值print(sum(t)) # 100 求和
4. 元组自带的两个方法
元组只有两个内置方法,都是查询类的:
t = (10, 20, 30, 20, 20, 50)# 统计次数print(t.count(20)) # 3# 找索引print(t.index(30)) # 2# print(t.index(99)) # 找不到报错:ValueError
5. 遍历元组
和列表遍历完全一致,常用 for 循环逐个取出元素:
t = ("小明", "小红", "小刚")for name in t: print(f"学生:{name}")
五、深入理解元组的「不可变性」
很多新手以为 “元组里的所有东西都不能改”,其实这个说法不准确。
核心规则
元组的不可变,指的是元素的引用不可变—— 也就是元组里每个位置指向的内存地址不能变。
- 如果元素是不可变类型(数字、字符串、布尔值),那确实完全不能改;
- 如果元素是可变类型(列表、字典),元素内部的内容是可以改的。
示例:元组嵌套列表
# 元组里放了一个列表t = (10, 20, ["a", "b", "c"])# ❌ 错误:不能修改元组的元素(不能换一个新的列表)# t[2] = ["x", "y"] 报错# ✅ 正确:可以修改列表内部的元素(列表本身是可变的)t[2].append("d")print(t) # (10, 20, ['a', 'b', 'c', 'd'])
解释:元组第三个位置指向的列表内存地址没变,只是列表自己的内容变了,所以不违反元组的不可变性。
六、元组的核心实用场景
新手经常问:既然列表功能更多,为什么还要用元组?主要有 4 个场景:
1. 保护数据不被意外修改
如果一组数据是固定的、不允许改动的,用元组更安全,避免代码里不小心改到数据。
# 比如一周七天,是固定不变的week = ("周一", "周二", "周三", "周四", "周五", "周六", "周日")
2. 函数返回多个值(最常用)
Python 函数可以返回多个值,本质就是返回了一个元组,这是日常开发最常见的元组用法。
# 定义函数,返回两个值def get_info(): name = "小明" age = 18 return name, age # 等价于 return (name, age)# 接收返回值,本质是元组解包res = get_info()print(res)print(type(res)) # <class 'tuple'># 更常用的写法:直接用两个变量接收n, a = get_info()print(n, a)
3. 变量交换
Python 里非常简洁的变量交换写法,底层就是元组打包 + 解包:
a = 10b = 20# 一行完成交换,不用中间变量a, b = b, aprint(a, b) # 20 10
原理:右边 b, a 先打包成元组 (20, 10),再解包赋值给左边的 a, b。
4. 作为字典的键
字典的键必须是不可变类型,列表不能当键,元组可以。
# 用坐标元组当字典的键position = { (0, 0): "起点", (10, 20): "终点"}print(position[(10, 20)]) # 终点
七、元组解包(重点,高频使用)
元组解包就是把元组里的元素,一次性赋值给多个变量。这是 Python 非常优雅的语法,日常开发用得非常多。
1. 基础解包
变量数量和元组元素数量必须一致:
t = ("小明", 18, 90)# 三个变量对应三个元素name, age, score = tprint(name)print(age)print(score)
2. 用 * 接收多余元素
如果元素很多,只想取前几个,剩下的用一个列表接收,可以用 *变量名:
t = (1, 2, 3, 4, 5, 6)a, b, *rest = tprint(a) # 1print(b) # 2print(rest) # [3, 4, 5, 6] 剩下的都放进列表里
* 也可以放在中间:
a, *mid, b = (1, 2, 3, 4, 5)print(a) # 1print(mid) # [2, 3, 4]print(b) # 5
3. 解包的其他用法
解包语法不止适用于元组,列表、字符串等序列都可以,核心逻辑是一样的。
八、元组和列表的类型转换
元组和列表可以互相转换,用对应类型的函数即可:
# 列表转元组lst = [1, 2, 3]t = tuple(lst)print(t) # (1, 2, 3)# 元组转列表t = ("a", "b", "c")lst = list(t)print(lst) # ['a', 'b', 'c']
实用技巧:如果想修改元组里的内容,可以先转成列表,改完再转回元组。
九、新手高频易错点总结
- 单个元素忘加逗号:
(10) 是整数,(10,) 才是元组,这是新手最容易踩的坑 - 尝试修改元组元素:元组不可变,不能通过索引赋值、不能增删元素,修改会直接报错
- 以为元组里的列表也不能改
- 解包时变量数量不匹配:变量数和元素数不一致会报错,多余元素可以用
* 接收 - 混淆元组和列表的方法:元组没有 append/pop/sort 等修改方法,只有 count 和 index