前言
简单记录一下Python中元组相关知识,记录与此,方便自己查看。
正文
什么是元组
元组(tuple)就是为“不该变的数据”准备的容器:创建之后不能直接增、删、改,因此也叫“不可变序列”。
可以这样理解:
列表像草稿纸,能反复擦改;元组像定稿,写好了就不该动。
# ① 空元组
empty = ()
# ② 多个值用逗号隔开(小括号可写可不写)
point = 120, 35
colors = ("red", "green", "blue")
# ③ 单个元素的元组:值后面必须加逗号
single = (10,) # 这是元组
not_tuple = (10) # 这只是整数 10!
# ④ 用 tuple() 把其他可迭代对象转成元组
tuple_from_list = tuple([1, 2, 3]) # (1, 2, 3)
tuple_from_string = tuple("hello") # ('h', 'e', 'l', 'l', 'o')最容易踩的坑:(10) 不是元组
判断元组的不是小括号,而是逗号。输出的时候,Python 总会给元组加上括号显示,但写代码时如果只有一个元素,就一定要加那个逗号。
print(type((10,))) # <class 'tuple'> print(type((10))) # <class 'int'>
存放类型
元组里可以放任何类型,而且不同类型可以混着放:
info = ("张三", 18, True, 99.5) # 字符串、整数、布尔值、浮点数
nested = ("A1001", (2026, 3, 26)) # 元组里面还能套元组常见的操作
元组虽然不能改,但可以正常读取,用法和列表一样。
info = ("张三", 18, "北京")
# ① 按位置取值,从 0 开始
print(info[0]) # 张三
# ② 负数索引:从末尾往前数
print(info[-1]) # 北京
print(info[-2]) # 18
# ③ 切片:取一部分,结果还是元组
nums = (10, 20, 30, 40, 50)
print(nums[1:4]) # (20, 30, 40)
print(nums[:3]) # (10, 20, 30)
print(nums[::2]) # (10, 30, 50)注意:切片得到的是新元组,原来的元组不会变。
下面这些操作都会报错:
nums = (10, 20, 30) nums[1] = 200 # TypeError:不能修改某个位置 nums.append(40) # AttributeError:没有 append nums.remove(20) # AttributeError:没有 remove del nums[0] # TypeError:不能删除
报错不是 Python 有问题,而是它故意拦住你,防止你改掉不该改的数据。
元组不能变,指的是每个位置指向谁不能变。如果某个位置放的是列表,这个列表里面的内容还是可以改的:
data = (10, 20, [30, 40]) data[2][0] = 300 # 可以:改的是列表里面的内容 # data[2] = [1, 2] # 不行:这是想把第 3 个位置整个换成别的
元组拼接,遍历,排序
a = (1, 2)
b = (3, 4)
print(a + b) # (1, 2, 3, 4) 拼接,得到新元组
print(a * 3) # (1, 2, 1, 2, 1, 2) 重复
print(len(a)) # 2 长度
print(2 in a) # True 是否包含
print(9 not in a) # True
# 遍历
for color in ("red", "green", "blue"):
print(color)
# 排序:sorted 会返回一个新列表,不会动原来的元组
nums = (3, 1, 4, 2)
print(sorted(nums)) # [1, 2, 3, 4]两个方法
元组不能增删改,所以方法很少,常用的就这两个:
nums = (1, 2, 2, 3, 2) print(nums.count(2)) # 3 统计 2 出现了几次 print(nums.index(2)) # 1 第一次出现的位置(从左往右找) # print(nums.index(9)) # 找不到会报 ValueError
元组拆包
基本拆包:把元组里的每个值,一次性放进对应的变量里。
person = ("张三", 18, "北京")
name, age, city = person
print(name) # 张三
print(age) # 18
print(city) # 北京官方文档管这个叫“序列拆包”。左边变量的个数必须和元组元素个数一模一样,否则会报错:
a, b = (1, 2, 3) # ValueError: too many values to unpack
用 \* 接收多余的元素
first, *middle, last = (1, 2, 3, 4, 5) print(first) # 1 print(middle) # [2, 3, 4] 带 * 的变量永远是列表 print(last) # 5 # * 可以放在任意位置 head, *tail = (10, 20, 30) print(head) # 10 print(tail) # [20, 30]
注意:同一层里最多只能有一个 *,而且至少要有一个普通变量和它搭配。
嵌套拆包
person = ("张三", (2000, 5, 18))
name, (year, month, day) = person
print(year) # 2000一行交换两个变量的值
a, b = 10, 20 a, b = b, a print(a, b) # 20 10
其实这行代码右边 b, a 会先打包成元组 (20, 10),再拆包给左边的 a, b。Python 里的“同时给多个变量赋值”,本质上就是先打包、再拆包。
函数返回多个值,其实就是返回元组
def get_min_max(numbers):
return min(numbers), max(numbers) # 自动打包成元组
scores = [88, 95, 72, 61, 100]
lowest, highest = get_min_max(scores) # 自动拆包
print(lowest, highest) # 61 100函数返回的“多个值”,Python 其实只返回了一个元组。所以元组虽然看着不起眼,但每天都在后台帮你做事。
namedtuple
普通元组只能写 p[0]、p[1],看代码的人很难知道 0 和 1 代表什么。collections.namedtuple 可以让元组的每个位置多一个名字:
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"]) # 定义一种“点”类型
p = Point(3, 4) # 创建实例
print(p.x) # 3 用名字访问
print(p.y) # 4
print(p[0]) # 3 用索引访问也行
print(p) # Point(x=3, y=4)
x, y = p # 照样可以拆包如果元组里的字段越来越多,可以改用 @dataclass,功能更强。但只想要“轻量、不可变、带名字”的结构,namedtuple 就够了。
元组能当字典的键
列表不能当字典的键,元组可以(前提是里面的元素都不可变):
# 用 (行, 列) 作为坐标键
grid = {(0, 0): "起点", (1, 2): "终点"}
print(grid[(1, 2)]) # 终点
# 如果元组里直接或间接含有列表,就不能当键
# bad = {([1, 2], 3): "值"} # TypeError原因是字典的键必须能被“哈希”(hashable),而可变的对象不能哈希。
使用场景
| 对比项 | 元组 tuple | 列表 list |
| 写法 | (1, 2, 3) | [1, 2, 3] |
| 能不能改 | 不可变 | 可变 |
| 里面元素的类型 | 常常是不同类型(表示一条记录) | 常常是同一种类型 |
| 常用方法 | 只有 count() 和 index() | append、remove、pop 等很多 |
| 典型用途 | 固定记录、函数返回值、字典的键 | 会不断增减的数据 |
用元组的场景
student = ("李雷", 16, "高一") # 一条固定记录
point = (120, 35) # 坐标
date = (2026, 3, 26) # 日期
color = (255, 128, 0) # RGB 颜色用列表的场景
tasks = ["写作业", "背单词", "跑步"]
tasks.append("复习数学") # 会不断增减,适合列表最常见的组合:外层列表,内层元组
orders = [
("A1001", "小王", 99.9),
("A1002", "小李", 59.8),
("A1003", "小张", 188.0),
]- 外层列表负责增加、删除订单
- 内层每个元组代表一条格式固定的订单
判断标准:数据会不会变?会变的用列表,固定不变或只读的用元组。
临时要改元组:先转成列表
nums = (10, 20, 30) temp = list(nums) # 转成列表 temp[1] = 200 # 在列表里改 nums = tuple(temp) # 再转回元组 print(nums) # (10, 200, 30)
小结
| 要点 | 说明 |
| 写法 | 用小括号,元素之间用逗号隔开 |
| 单个元素 | 一定要加逗号:(10,) |
| 能不能改 | 不能增、删、改,只能查和遍历 |
| 方法 | 只有 count() 和 index() |
| 最大亮点 | 拆包,以及函数“返回多个值” |
| 特殊用途 | 可以当字典的键;列表不行 |
| 选择原则 | 固定数据用元组,会变的数据用列表 |
参考文章
- AI
- Python文档
