11 Comments
User's avatar
⭠ Return to thread
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.