You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python列表与元组的内存存储机制解析及测试疑问解答

列表与元组的内存存储机制解析

我的观察与疑问

我知道Python列表是可变的,因为它们存储的是对元素的引用而非元素本身——列表变量的地址和元素的地址完全不同,我用这段代码验证了这一点:

输入代码

a_list = [1, 2, 3]

print(a_list, type(a_list), id(a_list))
for x in range(len(a_list)):
  print(x, type(x), id(x))

输出结果

[1, 2, 3] <class 'list'> 140125075225856
0 <class 'int'> 140125345710288
1 <class 'int'> 140125345710320
2 <class 'int'> 140125345710352

之前看到资料说元组存储在单个内存块中,我误以为元组的地址和它的元素地址是相同的。但测试元组时,发现元组变量和元素的地址也完全不同:

输入代码

a_tuple = (1, 2, 3)

print(a_tuple, type(a_tuple), id(a_tuple))
for x in range(len(a_tuple)):
  print(x, type(x), id(x))

输出结果

(1, 2, 3) <class 'tuple'> 140124247434368
0 <class 'int'> 140125345710288
1 <class 'int'> 140125345710320
2 <class 'int'> 140125345710352

显然我误解了列表和元组的内存管理逻辑,下面详细解析两者的存储机制:


核心结论先明确

列表和元组本质上都存储的是元素的引用,而非元素本身。两者的区别不在于是否存引用,而在于底层存储引用的数组是否可修改。

列表的存储细节

列表是动态可扩容数组:

  • 列表对象自身有独立的内存地址(id(a_list)返回的就是这个地址)
  • 列表内部是一个可以动态调整大小的数组,这个数组里的每个位置存放的是对应元素的内存地址(也就是引用)
  • 元素本身的内存位置和列表对象的位置完全分离,所以修改元素(比如a_list[0] = 4)只是把列表里对应位置的引用换成新元素的地址,列表对象的地址不会变;而添加/删除元素时,会根据需要扩容或收缩内部的数组,甚至重新分配内存块复制旧引用

元组的存储细节

元组是静态固定大小数组:

  • 元组对象同样有独立的内存地址(id(a_tuple)的结果)
  • 所谓“元组存储在单个内存块”,指的是元组用来存放元素引用的数组是一块连续的内存,而非元素本身和元组存在同一块内存里
  • 因为是静态数组,元组创建后大小无法修改,内部存储引用的数组也不会被调整,这就是元组“不可变”的核心原因——你没法改变元组里存储的引用集合,也没法改变元组的长度

补充:测试元素地址的正确方式

你之前的代码打印的是索引x的地址,不是元素的地址。要验证元素的引用,应该直接打印元素的id:

a_list = [1,2,3]
print("列表对象地址:", id(a_list))
for elem in a_list:
    print(f"元素{elem}的地址:", id(elem))

a_tuple = (1,2,3)
print("\n元组对象地址:", id(a_tuple))
for elem in a_tuple:
    print(f"元素{elem}的地址:", id(elem))

运行后会看到:

  • 列表/元组对象的地址,和每个元素的地址完全不同
  • 列表和元组里的同一个元素(比如整数1)地址相同,这是因为Python对小整数有缓存复用机制

内容的提问来源于stack exchange,提问作者Popsicle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 19:43:19