11 Comments
User's avatar
⭠ Return to thread
NMS's avatar

Yes, to clarify, whether it decides to create a new object or reuse the existing object depends on several factors. However, we can see this if we iteratively add:

>>> import collections

>>> letters = ['h', 'e','l', 'l','o',' ', 'w','o','r','l','d']

>>> ids = []

>>> string = ''

>>> for letter in letters:

... string = string + letter

... ids.append(id(string))

...

>>> print(collections.Counter(ids))

Counter({1601851586912: 3, 1601851587056: 3, 1601850291696: 2, 140723900781096: 1, 1601850286128: 1, 1601850284272: 1})

> Even when CPython does find cases when it reuses the same memory location, it's still creating a new object rather than mutating the old one.. It's all academic as this won't make any difference in practice, but I'd most definitely classify strings as an immutable type!

Not exactly. It's indeed mutating the old object. https://github.com/python/cpython/blob/3.12/Objects/unicodeobject.c#L10943-L10948

In practice, since it only does this when the ref count is one, it's the same as strings being immutable. I just find this corner case very fascinating.