CPython中相同字面量为何复用内存对象?
CPython中字面量对象复用的实现原理
你观察到的不可变字面量(整数、字符串)复用内存对象的现象,核心是CPython在编译阶段就完成了相同常量的合并,而非运行时动态搜索匹配,具体实现逻辑如下:
1. 不可变字面量的编译期驻留(Intern)机制
CPython的编译器在处理源代码时,会维护一个全局的常量池。当遇到整数、字符串这类不可变字面量时:
- 首次出现的字面量会被存入常量池,并生成对应的对象引用;
- 后续再遇到完全相同的字面量时,编译器不会重新创建新对象,而是直接复用常量池中已有的引用。
比如你代码里的1000和"car",无论是赋值给变量还是写在列表字面量里,只要字面内容完全一致,编译阶段就会被识别为同一个常量,最终字节码里指向的是同一个内存对象,所以运行时id()结果完全相同。哪怕是超出-5到256范围的超大整数(如1000000000000),只要字面完全一致,也会在编译期完成合并,这就是a is myList[0]返回True的原因。
2. 可变对象(如列表)不复用的原因
列表是可变对象,CPython不会对列表字面量做复用处理。因为如果复用同一个列表对象,当你修改其中一个引用指向的列表(比如a.append(4)),所有引用该对象的地方都会同步变化,这不符合开发者编写[1,2,3]两次时“创建两个独立列表”的预期。
因此,编译时每次遇到列表字面量,都会生成新的字节码指令来创建全新的列表对象,运行时自然会得到不同的id。
补充:和小整数池的区别
需要注意,-5到256的小整数预创建是运行时的优化机制,和你观察到的大整数复用逻辑不同。大整数、字符串的复用完全是编译阶段的常量合并结果,和小整数池无关。
内容的提问来源于stack exchange,提问作者SuperHanz98
相关产品推荐
相关产品推荐

