我的图片 · 在线免费的图片处理工具

前言

简单记录一下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()
最大亮点拆包,以及函数“返回多个值”
特殊用途可以当字典的键;列表不行
选择原则固定数据用元组,会变的数据用列表

参考文章

  1. AI
  2. Python文档

暂无评论

评论审核已启用。您的评论可能需要一段时间后才能被显示。

none
暂无评论...