Python 的列表 list 和元组 tuple 有啥本质区别?啥时候用谁更合适?

Python 的列表 list 和元组 tuple 有啥本质区别?啥时候用谁更合适?

一句话先看结论

  • 列表 list:能改、能增删,万能"购物车",适合会变的序列数据。
  • 元组 tuple:不能改,创建后就"锁死",更省内存、更快读,适合固定不变的数据,比如常量配置、坐标、不可变键等。

为什么会这样?因为 tuple 不允许改动,解释器可做内存和访问优化;list 需要支持增删改,内部会额外预留空间并有更多开销。

语法与不可变性

  • 列表:用方括号 [],可以随时改元素、append、pop。
  • 元组:用圆括号 (),一旦创建不能改(改就报错 TypeError)。

示例:

python 复制代码
# 列表:能改
fruits = ["apple", "banana"]
fruits.append("pear")       # OK
fruits[^0] = "orange"        # OK
print(fruits)               # ['orange', 'banana', 'pear']

# 元组:不能改
pos = (10, 20, 30)
# pos[^0] = 99               # TypeError: 'tuple' object does not support item assignment
print(pos)                  # (10, 20, 30)

这种"不可变"带来的副作用是:只要里面的元素也都不可变,元组就能当字典的键或放进 set,因为它可哈希;列表不行。

python 复制代码
# 元组可做 dict 的键(元素都不可变时)
prices = {("apple", "small"): 3.5, ("apple", "large"): 5.0}
print(prices[("apple", "small")])  # 3.5

# 列表做键会报错
# bad = {[1, 2]: "x"}  # TypeError: unhashable type: 'list'

不可变还带来另一个好处:并发里更安全(没人能改它),也更可预测(不担心被无意修改)。

性能与内存:为什么 tuple 往往更省更快(读多改少场景)

  • 内存:相同元素下,tuple 一般比 list 占用更少内存,因为它不需要为"未来的增长"预留空间,也没有可变带来的额外管理开销。
  • 访问/迭代:tuple 往往稍快于 list,尤其"只读访问"场景,因为解释器可针对不可变对象做优化(比如更紧凑的布局、少一点边界检查等)。[2][3][1][5]
  • 但注意:很多日常小规模场景下,这种差距并不大,写业务代码不必为每一次小访问纠结,先选语义更合适的数据结构才是正解。

简单对比(不同机器数值会不同,仅示意):

python 复制代码
import sys, time

data_list = [i for i in range(100000)]
data_tuple = tuple(data_list)

print("list bytes:", sys.getsizeof(data_list))
print("tuple bytes:", sys.getsizeof(data_tuple))
# 一般会看到 tuple 更小[^1][^7][^10]

# 简单迭代耗时对比(多次取平均更客观)
t0 = time.perf_counter()
s = 0
for x in data_list:
    s += x
t1 = time.perf_counter()

s = 0
for x in data_tuple:
    s += x
t2 = time.perf_counter()

print("list iterate:", t1 - t0)
print("tuple iterate:", t2 - t1)
# 通常 tuple 稍快或相近,尤其纯读取场景[^1][^3][^6]

为什么会更省更快?大白话解释:

  • list 是"可扩容的箱子",需要留富余空位,随时支持 append/insert/pop,因此多点管理成本。
  • tuple 是"密封好的盒子",大小固定,解释器一次到位分配,更紧凑,拿数据更省事。

另外,tuple 在编译层面还有一些可优化场景,比如"常量折叠":常量元组可在编译期直接预先构建,少走些指令。

什么时候用 list,什么时候用 tuple?

  • 需要改动(增删改顺序)的序列:用 list,比如收集请求、动态队列、批量构建数据。
  • 固定不变、只读的数据:用 tuple,比如常量配置、固定坐标、RGB 颜色、数据库字段定义等。
  • 需要当 dict 的键或放入 set:用 tuple(且内部元素也要不可变)。
  • 性能敏感、读多写少且数据大:倾向 tuple,省内存、迭代稍快。
  • API 设计想表达"这是只读返回值":返回 tuple 让调用者一看就知道不可改,更安全。

示例:配置项、坐标等固定数据用 tuple

python 复制代码
# 常量配置
ALLOWED_ROLES = ("admin", "editor", "viewer")  # 不希望被修改[^1][^6]

# 坐标 / 颜色
origin = (0.0, 0.0)
white = (255, 255, 255)

# 作为字典键
edge_weights = {
    ("A", "B"): 1.2,
    ("B", "C"): 0.8,
}  # 键是不可变的元组,语义清晰[^6][^15]

示例:会变的数据用 list

python 复制代码
# 任务队列(会变化)
tasks = []
tasks.append("crawl_page")
tasks.append("parse_html")
tasks.pop(0)  # 处理一个
print(tasks)

一些容易踩坑的小点

  • tuple 不可变,但"浅不可变":如果元组里放的是可变对象,比如列表,那么列表的内容还是能改的;只是不能改"这个位置放的是谁"。
python 复制代码
t = (1, [2, 3], 4)
t[^1].append(99)     # 可以,因为改的是内部列表的内容
print(t)            # (1, [2, 3, 99], 4)
# 但 t[^1] = [8, 9] 不行,会 TypeError
  • 想"增加一个元素"的 tuple,本质是创建了一个新 tuple,并不会原地改旧的:
python 复制代码
t = (1, 2, 3)
t2 = t + (4,)   # 新建
print(t, "=>", t2)  # (1, 2, 3) => (1, 2, 3, 4)

进阶细节:为什么 tuple 构建/读取可能更快?

  • 不可变意味着解释器知道"大小和内容不变",可一次性分配、更紧凑地存储,访问时开销更少;同时一些常量元组还能在编译时被折叠,减少运行期开销。
  • list 为了支持动态增长,会"过度分配"预留空位,增删时需要移动或扩容,带来额外成本;但正因如此,它对频繁变动的场景更友好。

小结式指南

  • 优先按语义选型:会变→list;不变→tuple。
  • 想要更省内存、稍快迭代、可当 dict 键/放 set,且数据确实不需要改→tuple。
  • 实际性能别猜,真有需求就用 time/perf_counter 和 sys.getsizeof 做小基准对比再决定。

参考要点基于公开资料的共识:tuple 不可变带来更好的内存紧凑与一定场景下的访问优势;list 提供灵活的增删改,是通用工作马。

相关推荐
Cha0DD2 小时前
【由浅入深探究langchain】第二十集-SQL Agent+Human-in-the-loop
人工智能·python·ai·langchain
Cha0DD2 小时前
【由浅入深探究langchain】第十九集-官方的SQL Agent示例
人工智能·python·ai·langchain
智算菩萨3 小时前
【Tkinter】4 Tkinter Entry 输入框控件深度解析:数据验证、密码输入与现代表单设计实战
python·ui·tkinter·数据验证·entry·输入框
七夜zippoe4 小时前
可解释AI:构建可信的机器学习系统——反事实解释与概念激活实战
人工智能·python·机器学习·可解释性·概念激活
桌面运维家5 小时前
Windows权限管理进阶:UAC配置与安全策略实战
windows
paeamecium6 小时前
【PAT甲级真题】- Student List for Course (25)
数据结构·c++·算法·list·pat考试
YuanDaima20487 小时前
[CrewAI] 第15课|构建一个多代理系统来实现自动化简历定制和面试准备
人工智能·python·面试·agent·crewai
WHS-_-20227 小时前
Python 算法题学习笔记一
python·学习·算法
码界筑梦坊8 小时前
353-基于Python的大湾区气候数据可视化分析系统
开发语言·python·信息可视化·数据分析·django·vue·毕业设计
如何原谅奋力过但无声8 小时前
【chap11-动态规划(上 - 基础题目&背包问题)】用Python3刷《代码随想录》
数据结构·python·算法·动态规划