Python中元组和列表差异:底层结构分析

引入:

在pymysql中,查询函数fetchall()返回值是一个元组,为什么要以元组形式返回呢

  1. 元组**「不可变」**,保护查询数据不被篡改

2. 元组性能更高,适配大数据量查询

  1. 语义匹配:数据库行是「固定结构数据」

针对2,为什么元组开销比列表小且性能更高?

这是一个非常棒的深入提问!元组(tuple)的开销比列表(list)小,根源只有一个:元组是不可变类型,列表是可变类型

列表要随时修改、扩容,所以内存里必须存:

  • 数据本身
  • 当前元素个数len() 用)
  • 已分配的总容量(预留空位,防止频繁扩容)
  • 指向数据区的指针
  • 扩容相关的标记位

元组长度固定、不能修改,所以内存里只存:

  • 数据本身
  • 固定的长度(创建时就定死,不用变)

接下来再从底层数据结构的实现来分析这个问题:

列表底层的 3 个核心实现细节

1. 连续内存存储(和元组一样)

列表的所有元素在内存里是紧挨着存放的,这是数组的本质:

  • 优点:随机访问超快 (通过索引 list[i] 取值,时间复杂度 O (1))
  • 这也是数据库 fetchall 用「数组结构(元组)」的原因:遍历、索引查询速度拉满

2. 存的是「对象指针」,不是数据本身

Python 是动态语言,列表能存任意类型(数字、字符串、对象、甚至另一个列表),底层原理是:列表只存指向真实数据的内存地址(指针),不直接存数据。

3. 关键:预分配内存 + 动态扩容(列表开销大的根源)

这是列表和元组最大的区别,也是列表开销更高的核心:

  • 元组:创建时只分配刚好存数据的内存
  • 列表:解释器会提前多分配一部分空闲内存 (预分配),为了应对 append()extend() 增删操作

列表每次扩容需要4个步骤:

  1. 申请新内存 :解释器找一块更大的连续内存
  2. 复制数据 :把旧内存里的所有数据原封不动拷贝到新内存
  3. 添加新元素 :把新元素5放进新内存的空位
  4. 丢弃旧内存 :释放原来的小内存(还给系统),列表直接指向新的大内存

总结:

  1. 列表底层是动态数组 :需要预分配内存、维护容量 / 长度,所以开销大
  2. 元组底层是静态数组 :无预分配、无扩容,结构精简,所以开销小
  3. 数据库 fetchall 返回元组:查询数据只读、不需要修改,用静态数组(元组)速度更快、更省内存,完美适配大数据查询场景
相关推荐
红宝村村长1 小时前
windows笔记本双系统ubuntu设置
开发语言
威联通安全存储1 小时前
TS-h2287XU-RP 在家电制造总装与质检数据场景的部署
python·制造
泡泡鱼(敲代码中)2 小时前
Python 字符串 str 完整学习笔记
python·学习
troy1282 小时前
Python 基础语法(八):Web 后端开发、数据分析与可视化、网络爬虫、人工智能 / 大模型应用
前端·python·数据分析
菜鸟~noob2332 小时前
【电子战】第15篇:混合定位——TDOA/FDOA/AOA 联合【含matlab代码】
开发语言·matlab
我不会起名字3223 小时前
一天一道算法题(34):回溯法的经典例题(子集)
java·数据结构·python·算法·golang·深度优先·力扣
ThornArmor3 小时前
重铸1996|肉体渲染:关节的裂缝:分段模型积木拼装与未成熟的 RSP 矩阵骨骼动画形变
c语言·汇编·c++·python·硬件架构·游戏机
毕业设计7033 小时前
(免费领源码)基于Python的博物馆研学活动管理系统的设计与实现22724- java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
python·mysql·随机森林·pycharm·django·flask·推荐算法
kyrie_sakura3 小时前
python学习笔记15 -- Anaconda,Jupyter,numpy
python·学习·jupyter·numpy
Dreams_l4 小时前
死信队列和延迟队列介绍
java·开发语言