Python的字符串不是不可变的吗?

3

直到现在我一直认为Python字符串是不可变的,但当我尝试这样做时,我感到困惑了。

>>> a
'hello world !'
>>> id(a)
140521043795728
>>> a+="d"
>>> id(a)
140521043795728
>>> a+="d"
>>> id(a)
140521043795728
>>> a
'hello world !dd'

如果我使用+=运算符,尽管字符串已更改,但它不会更改对象ID。在这种情况下发生了什么?
现在有点不同?https://ideone.com/eg1SIN 有人能解释一下这里发生了什么吗?

尝试在添加之前添加 b = a,保持 b 不变,并打印 ab 的 id。 - Colonel Thirty Two
@ColonelThirtyTwo:https://ideone.com/eg1SIN 这是怎么回事? - bakar
@William_Wilson:是的,我看到了,但那是稍微不同的观察。 - bakar
Python只是重复使用了ID,但不可变字符串和变量的现象完全相同。然而,我确实看到了扩展我发布链接中找到的信息的用处。 - William_Wilson
那是内存地址,你不再使用原始的 a 对象,因此 Python 可以自由地重用该地址。正如 Colonel 所评论的那样,保留对 a 的引用,你将会看到不同的行为。 - Padraic Cunningham
2个回答

10

id 返回一个整数值,该值对于所传递的对象是唯一的。如果 a 是字符串 'hello world !' 的唯一引用,则执行 a += "b" 可能会在创建字符串 'hello world !b' 之前结束字符串 'hello world !' 的生命周期,因此旧字符串的 ID 被重用 (这是完全有效的行为)。

添加对字符串 'hello world !' 的另一个引用 (例如,在修改 a 之前执行 b = a) 应该导致 ID 分歧。


那么创建/分配Python对象的id的逻辑/算法是什么?Python解释器如何分配/生成id?有任何相关资料吗? - bakar
1
cpython解释器只是返回对象的地址,但这只是一个实现细节。唯一的保证是,只要对象存在,它就有一个永远不会改变的唯一ID。 - Colonel Thirty Two

1

字符串对象本身是不可变的,但是根据Python文档,具有非重叠生命周期的对象可能具有相同的id()值。


根据Python文档,生命周期不重叠的两个对象可能具有相同的id()值。我已经更正了我的答案以反映这一点。 - Alex
对象是一个内存地址。 - Padraic Cunningham
这是正确的。正如内置帮助所述:id(obj, /) 返回对象的标识。这保证在同时存在的对象中是唯一的。 (CPython使用对象的内存地址。)因此,只要它存在,它就是唯一的,但是在会话期间,内存地址可能会被重新分配。 - Ben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接