Python如何为字符串分配id?相同值字符串操作id不一致如何解释
问题现象解释
核心基础前提
Python中字符串是不可变对象,所有对字符串的操作如果逻辑上会生成新值,都会默认创建新的字符串对象,仅当CPython解释器内置的优化逻辑判断可以复用现有对象时,才会直接返回原对象,才会出现id不变的情况。所有id变化/不变的差异都是CPython针对不同场景做的特定优化导致的,并非Python语言的标准规定。
各场景逐一解释
- 赋值
"a"时总是返回相同id
这是CPython的字符串驻留(intern)机制导致的:长度为1的ASCII字符、符合标识符命名规则的短字符串会被默认加入内部缓存池,全局复用同一个对象,因此多次赋值"a"都会指向缓存池中的同一个对象,id完全相同。 - 每次调用
a.lower()都会改变idstr.lower()方法的CPython实现中,没有做「返回值与原字符串值相等时直接返回原对象」的优化,哪怕输入已经是全小写字符串,每次调用都会生成新的临时字符串对象,因此每次id都会变化。 a[::-1]操作会改变id
反转切片的实现逻辑默认生成新字符串对象,哪怕反转后的值和原字符串完全相同,也不会做返回原对象的优化,因此id会变化。a[:1]操作不会改变id
这是CPython针对短字符串切片做的特定优化:当切片的结果与原字符串完全相等时(长度为1的字符串取前1位刚好符合这个条件),会直接返回原对象,因此id不变。- 调用
g(a)不会改变id
函数g中"" + x的拼接操作,CPython做了专门优化:空字符串和任意字符串拼接时,直接返回原字符串对象,不会创建新对象,因此id不变。 - 调用
f(a)会改变id
函数f中先执行x + x生成新字符串"aa",再取[:1]得到值为"a"的字符串,这个结果刚好命中字符串驻留规则,直接返回了缓存池中的"a"对象,因此id从之前的临时对象id切换为缓存池中的固定"a"对象id。
注意事项
以上所有行为都是CPython 3.8版本的实现细节,不属于Python语言规范的强制要求,不同Python版本、不同解释器(如PyPy)的表现可能存在差异,实际开发中不要依赖字符串id是否相同来判断值是否相等,应该使用==运算符判断值相等,is运算符仅用于判断是否为同一个对象。
内容的提问来源于stack exchange,提问作者Antoine
相关产品推荐
相关产品推荐

