元组 (Tuple)
了解元组不可变特性、拆包技巧、与列表的区别
元组 (Tuple)
元组和列表很像,但有一个关键区别:元组不可修改。这个看似"限制"的特性,恰好是它的最大优势。
学完本章你将掌握: 元组创建、拆包、不可变性、命名元组、与列表的选择。
一、创建元组
python
# 圆括号创建
t1 = (1, 2, 3)
# 可以省略括号
t2 = "a", "b", "c"
# 单元素元组(注意逗号!)
single = (42,) # 这是元组
not_tuple = (42) # 这只是整数 42!
# tuple() 构造函数
t3 = tuple([3, 1, 4]) # 从列表创建
t4 = tuple("hello") # ('h','e','l','l','o')
💡 单元素陷阱:
(42)被解析为数学表达式的括号,不是元组。必须加逗号(42,)。
二、访问元素
与列表完全相同的索引和切片:
python
point = (10, 20, 30, 40)
print(point[0]) # 10
print(point[-1]) # 40
print(point[1:3]) # (20, 30)
print(len(point)) # 4
三、不可变性
python
t = (1, 2, 3)
# ❌ 这些操作都会报错
# t[0] = 10 # TypeError: 'tuple' object does not support item assignment
# t.append(4) # AttributeError
# t.remove(1) # AttributeError
# ✅ 只能读取和计算
print(1 in t) # True
print(t.count(2)) # 1
print(t.index(3)) # 2
print(sum(t)) # 6
print(max(t)) # 3
💡 不可变的好处:数据不会被意外修改,可以安全地用作字典的键;多线程环境下不需要加锁。
四、元组拆包
Python 最优雅的特性之一:
python
# 基础拆包
name, age, city = ("小明", 20, "北京")
print(f"{name},{age}岁,来自{city}")
# 交换变量(无需临时变量!)
a, b = 10, 20
a, b = b, a
print(a, b) # 20 10
# 星号拆包(收集剩余元素)
first, *middle, last = (1, 2, 3, 4, 5)
print(first) # 1
print(middle) # [2, 3, 4](中间是列表)
print(last) # 5
# 忽略不需要的值(用 _)
name, _, city = ("小明", 20, "北京")
print(name, city) # 小明 北京
实战:函数返回多个值:
python
def divide(a, b):
quotient = a // b
remainder = a % b
return quotient, remainder # 实际返回元组
q, r = divide(10, 3)
print(f"商 {q},余 {r}") # 商 3,余 1
五、元组 vs 列表
| 特性 | 列表 | 元组 |
|---|---|---|
| 创建 | `[1,2,3]` | `(1,2,3)` |
| 修改 | ✅ 可增删改 | ❌ 不可修改 |
| 性能 | 稍慢 | 稍快 |
| 内存 | 更大 | 更小 |
| 作字典键 | ❌ 不能 | ✅ 可以 |
| 适用场景 | 动态数据 | 固定数据 |
python
# 什么时候用元组?
# 1. 坐标、颜色值等固定数据
point = (1920, 1080)
rgb = (255, 128, 0)
# 2. 数据库查询结果
user = (1, "小明", "beijing")
# 3. 需要保护的常量
STATUS_CODES = (200, 301, 404, 500)
六、命名元组 namedtuple
让元组像对象一样通过名字访问:
python
from collections import namedtuple
# 定义一个"学生"命名元组
Student = namedtuple("Student", ["name", "age", "score"])
s1 = Student("小明", 20, 95)
s2 = Student("小红", 22, 88)
# 像属性一样访问
print(s1.name) # 小明
print(s1.score) # 95
print(s2.age) # 22
# 仍然是元组,可以用索引
print(s1[0]) # 小明
小结
- 元组用
(),不可修改——这是它和列表的唯一核心区别 - 拆包
a, b = (1, 2)简洁优雅 - 星号拆包
*middle收集剩余元素 - 需要不可变数据时优先用元组(更安全、更快)
namedtuple结合了元组的轻量和对象的可读性
小练习
- 用拆包交换两个变量的值
- 写一个函数
min_max(nums)返回元组(最小值, 最大值) - 创建一个
Point命名元组,包含 x, y 坐标
💬 下一章预告:接下来学习集合 (Set)——自动去重的数据结构。