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

Python字符串驻留机制测试结果差异原因咨询

Python字符串驻留机制测试中的ID差异原因解析

问题背景

我正在学习Python字符串驻留机制,执行了如下测试代码:

# short str
list_short_str = ['0', str(0), chr(48), ''.join(['0']), '0'.join(('','')), '230'[-1:], ''+'0'+'', 'aaa0a'.strip('a')]

print("short str id:")

for item in list_short_str:
    print(id(item))
    
# long str
list_long_str = ['hello', 'hel'+'lo', 'helloasd'[:5], ''.join(['h','e','l','l','o']), '  hello '.strip(' ')]

print("long str id:")

for item in list_long_str:
    print(id(item))

得到输出结果:

short str id:
2450307092400
2450856182064
2450307092400
2450307092400
2450298848880
2450307092400
2450307092400
2450307092400
long str id:
2450855173808
2450855173808
2450856182256
2450856182320
2450856182192

在IDLE、PyCharm和Jupyter三种IDE中测试均得到一致结果:

  • 短字符串'0'的相关测试里,str(0)和'0'.join(('',''))的id不同,其余操作生成的字符串id均相同;
  • 长字符串'hello'的相关测试里,仅'hello'与'hel'+'lo'的id相同,其余操作生成的字符串id均不同。

查阅相关资料未找到原因,恳请解答该差异产生的原因。


原因解析

Python的字符串驻留(string interning)是内存优化机制,通过复用已有字符串对象减少内存占用,但触发规则并非覆盖所有场景,核心取决于字符串是否在编译期可确定,以及运行时操作是否主动触发驻留。

一、短字符串'0'的ID差异分析

  1. str(0)生成的字符串未被驻留
    str(0)是运行时调用内置函数生成的字符串,不属于编译期字面量。Python自动驻留机制默认仅对编译期可确定的字面量(如直接写的'0')、编译期可计算的表达式(如''+'0'+'')进行驻留,动态生成的结果不会自动加入驻留池,除非显式调用sys.intern()。

  2. '0'.join(('',''))生成的字符串未被驻留
    str.join()方法的返回结果是否驻留取决于底层实现:对于空序列拼接(两个空字符串用'0'连接),虽然结果是'0',但join是运行时动态创建新字符串的逻辑,不会主动触发驻留——毕竟join的场景多为动态拼接任意内容,Python不会默认对这类结果做驻留优化。

  3. 其余操作触发驻留的原因

  • chr(48):返回的单个ASCII字符属于Python自动驻留范围,恰好返回'0',直接复用驻留池中的对象;
  • ''.join(['0']):当join的序列仅含一个字符串元素时,CPython底层会直接返回该元素本身,因此复用驻留池中的'0';
  • '230'[-1:]:切片结果为单个已驻留的字面量字符,直接复用驻留池对象;
  • ''+'0'+'':属于编译期可计算的表达式,编译器会提前优化为'0',使用驻留池对象;
  • 'aaa0a'.strip('a'):strip返回的'0'是单个ASCII字符,CPython底层会复用驻留池中的已有对象。

二、长字符串'hello'的ID差异分析

  1. 'hello'与'hel'+'lo'ID相同
    'hel'+'lo'是编译期可计算的拼接表达式,Python编译器会在编译阶段将其合并为'hello'字面量,因此和直接写的'hello'共享同一个驻留对象。

  2. 其余操作未触发驻留的原因

  • 'helloasd'[:5]:切片是运行时动态生成字符串的操作,即使结果是'hello',也不会自动驻留——切片结果可能是任意子串,Python不会默认对这类动态生成的长字符串做驻留;
  • ''.join(['h','e','l','l','o']):join运行时动态拼接字符序列生成的字符串,不会主动加入驻留池,因此创建新对象;
  • ' hello '.strip(' '):strip运行时处理后返回的结果属于动态生成字符串,同样不会自动触发驻留,生成新对象。

补充:CPython的自动驻留规则主要覆盖:

  • 编译期字面量(数字、单个字符、符合规则的短字符串)
  • 编译期可计算的字符串拼接(仅当所有操作数都是字面量时)
    运行时动态生成的字符串,需显式调用sys.intern()才会进入驻留池。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 01:47:15