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

Fun fact: At least in CPython, strings are technically not immutable (although for all practical purposes they are). This is due to an optimization made for string addition.

If you do a:

string = string + stringtwo

and the reference count of string before the operation is one, then CPython reuses string instead of allocating a new memory location. You can check this by doing id(string) before and after the operation.

Stephen Gruppetta's avatar

But:

```

name = "hello"

print(id(name))

# 4378810272

name = name + "bye"

print(id(name))

# 4379196848

```

This is 3.12

Stephen Gruppetta's avatar

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, I'd say. But using the same memory address. It's all academic as this won't make any difference in practice, but I'd most definitely classify strings as an immutable type!

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.