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

Python列表与字符串切片的id()返回值差异及原理问询

以下结论均基于官方CPython解释器实现,其他Python解释器可能存在逻辑差异。

问题1:为何id(a[:]) == id(a[:])的执行结果为True?

对列表执行[:]全切片操作会生成一个新的浅拷贝列表对象,理论上两个切片操作应该生成两个不同对象,id应该不同,出现相等的原因是CPython的引用计数内存回收机制:

  • 第一个a[:]执行完后生成了临时列表对象,传入id()函数拿到地址后,这个临时对象没有任何变量持有引用,引用计数归零,立刻被回收,对应的内存地址被释放回内存池。
  • 第二个a[:]生成新列表对象时,刚好申请到了刚被释放的这块内存地址,所以两次id()返回的地址值相同。

这个结果是内存地址复用的偶然结果,两个临时对象的生命周期没有重叠,并不代表两个切片生成的是同一个对象。

问题2:为何先执行b = a[:]后,id(b) == id(a[:])的结果为False?

当你把第一个切片结果赋值给b之后,这个切片生成的列表对象就被变量b持有,引用计数至少为1,不会被内存回收,它占用的内存地址会一直被占用。后续再执行a[:]会生成一个全新的列表对象,需要申请新的内存地址,两个对象生命周期重叠,不可能共用同一个内存地址,所以id比较结果为False。

问题3:若将列表替换为字符串,上述两类比较结果均为True,背后的底层原理是什么?

字符串是不可变对象,CPython对不可变序列的操作有专门的优化:

  1. 首先对于不可变序列的全切片操作,CPython会直接返回原对象的引用,根本不会生成新对象——因为不可变对象无法被修改,返回自身不会有线程安全或者数据被篡改的风险,同时还能节省内存开销。所以s[:] is s的结果本身就是True,两次取id自然完全相同。
  2. 除此之外CPython还有字符串驻留优化,符合规则的字符串会被缓存到全局字符串池里,所有相同内容的字符串都会复用同一个对象实例,哪怕你通过其他方式生成相同内容的字符串,也会直接返回池中的已有对象引用,不会额外创建新对象。

两种优化叠加,不管是连续两次取s[:]的id,还是先赋值给变量再和后续s[:]的id比较,结果都是True。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 13:54:04