🎯「元组」全景速通:从“不可变列表”到“函数式利器”的一次看懂!

71 阅读2分钟

不是“只读列表”,不是“小括号套元素”,
这是一篇能跑、能改、能装逼的元组全景笔记——
()@dataclass,从“哈希钥匙”到“星号 unpacking”,

微信图片_20251014151033_10_20.jpg

① 元组是什么?一句话定义 📜

有序、不可变、可哈希、可迭代的序列类型。
创建后不能增删改,但内部可变元素可以改(嵌套陷阱)。


② 创建语法:3 种写法一次记牢 📝

# 1. 小括号(推荐)
t = (1, 2, 3)

# 2. 无括号(Pythonic)
t = 1, 2, 3

# 3. 单元素逗号(必考)
single = (42,)   # 不是 (42)

口诀:“单元素逗号,无括号也行,小括号最清晰!”


③ 核心操作:一张表速查 ⚡️

操作代码结果
索引t[0]1
切片t[::-1](3, 2, 1)
长度len(t)3
拼接t + (4,)(1, 2, 3, 4)
重复(0,) * 3(0, 0, 0)
统计t.count(2)1
查找t.index(3)2

没有 append / extend / remove!想改→先转 list


④ 哈希钥匙:当 dict/set 的键 🗝️

# 合法:元组里全是不可变元素
loc = {(116.4, 39.9): "北京", (121.5, 31.2): "上海"}

# 非法:内含列表
# loc = {(1, [2, 3]): "home"}  # TypeError: unhashable type: 'list'

结论:“元组可哈希,但内部必须全是可哈希元素”


⑤ 拆包艺术:一行赋值多个变量 🎁

# 位置拆包
x, y, z = (1, 2, 3)

# 星号拆包
first, *middle, last = (1, 2, 3, 4, 5)   # middle=[2,3,4]

# 函数多返回
def divmod(a, b): return a // b, a % b
q, r = divmod(10, 3)   # q=3, r=1

口诀:“星号收中间,位置收两边,函数返回自动打包”


⑥ 性能对比:比 list 快 & 省内存 🚀

import sys, timeit

lst = [1, 2, 3, 4, 5]
tup = (1, 2, 3, 4, 5)

sys.getsizeof(lst)  # 104 bytes
sys.getsizeof(tup)  #  80 bytes  ↓23%

timeit.timeit('x[2]', globals={'x': lst})  # 28 ns
timeit.timeit('x[2]', globals={'x': tup})  # 22 ns  ↓21%

结论:迭代、索引、哈希都略快,大数据优先 tuple


⑦ 嵌套陷阱:内部可变元素可改 💣

# 元组本身不可变,但内部列表可以改
t = (1, [2, 3], 4)
t[1].append(4)        # OK → (1, [2, 3, 4], 4)
t[0] = 9              # TypeError!不能改顶层

规避:使用 tuple 存不可变数据,或 dataclass 冻结结构


⑧ 现代替代:dataclass + frozen 🧊

from dataclasses import dataclass

@dataclass(frozen=True)
class Point:
    x: int
    y: int

p = Point(1, 2)
p.x = 3  # dataclasses.FrozenInstanceError

结论:需要字段名 + 类型提示 → 用 frozen dataclass 代替裸 tuple


⑨ 趣味实战:元组解谜小游戏 🎲

import random, time

# 谜题:元组里藏密码
puzzle = (3, 1, 4, 1, 5)
key = "".join(str(x) for x in puzzle)
print("🔑 密码:", key)  # 31415 → π 前5位

🏁 一句话口诀(背它!)

**“单元素逗号,星号收中间,哈希当钥匙,性能省内存,嵌套改内部,冻结用 dataclass!”**🎵