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

为何Pandas DataFrame单元格的id会随每次执行变化?

理解Pandas视图中元素ID变化的原因

首先明确两个核心事实:

  • 你定义的df1 = df.iloc[:3, :]确实是df的视图,二者共享底层的numpy数组内存,修改df1的元素会直接影响df,这一点没有问题。
  • 你看到的ID变化和看似矛盾的相等判断,本质上是Python的id()函数特性 + Pandas访问单个元素的实现逻辑共同导致的,和视图本身的内存共享无关。

1. 为什么每次访问元素的ID会变化?

当你通过df.loc[0, 'a']或df1.loc[0, 'a']获取单个元素时,Pandas并不会直接返回底层数组中对应内存位置的引用。相反,它会创建一个新的标量对象(这里是numpy.int64类型,因为你的数据来自np.arange)来包装这个值。

每次执行df.loc[0, 'a'],都会生成一个全新的标量实例,这个实例的内存地址(也就是id()返回的值)自然会不同——除非前一个实例已经被Python的垃圾回收器回收,新实例刚好复用了同一个内存地址(这就是你第一次执行时ID相同的原因)。

2. 为什么偶尔打印的ID不等,但id(...) == id(...)返回True?

这是Python中id()函数的一个常见“陷阱”:id()返回的是对象在其生命周期内的内存地址。当你在同一行执行id(df.loc[0, 'a']) == id(df1.loc[0, 'a'])时:

  • 第一个df.loc[0, 'a']创建的标量对象,在id()调用完成后就没有任何引用了,会被立即标记为可回收。
  • 紧接着创建的df1.loc[0, 'a']标量对象,可能刚好被分配到了刚刚释放的内存地址上,所以两者的id()相等,判断返回True。

但如果你分开两行打印,中间可能有其他操作(哪怕只是Python解释器的内部操作),导致第一个对象的内存地址被其他对象占用,第二个对象只能用新的地址,所以打印出的ID就不一样了。

3. 验证视图共享内存的正确方式

如果要确认df和df1确实共享底层内存,不要通过单个元素的id()来判断,而是直接修改视图的元素,看原DataFrame是否变化:

df1.loc[0, 'a'] = 999
print(df.loc[0, 'a'])  # 会输出999,说明底层内存共享

或者直接查看底层数组的内存地址:

print(id(df.values))
print(id(df1.values))  # 两者ID相同,说明共享同一个numpy数组

总结一下:你看到的ID变化是因为每次访问元素都生成了新的包装对象,而视图本身的底层内存是完全共享的——这是Pandas的设计逻辑(方便标量操作)和Python内存管理机制共同作用的结果。

内容的提问来源于stack exchange,提问作者Y. Gao

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:16:19