-5

Strings are immutable in Python, but in below example, a new id is generated once I start concatenating letters to initial string, this id remains constant until I assign a new string to the same name reversedString. As per my understanding of immutability, in each concatenation new id must be assigned as strings are immutable, not like lists. Please clarify the same.

sample = "hello"
print(id(sample)) # 1635882773744

sample += "A"
print(id(sample)) # 1635885488752

sample += "D2"
print(id(sample)) # 1635885488752

sample += "EWWW"
print(id(sample)) # 1635885488752

sample = "R"
print(id(sample)) # 1635795667504

Output:

1635882773744
1635885488752
1635885488752
1635885488752
1635795667504
Tibebes. M
  • 6,940
  • 5
  • 15
  • 36
Sujith
  • 1
  • 5
  • 1
    The id tells you which memory location the string is saved at. Memory locations being reused only indicates a memory management system, it does not indicate that strings are mutable. – deceze Aug 24 '20 at 06:39
  • Is there any way to test immutability of strings in above example? But how come ids are same only while concatenating, I am confused there. – Sujith Aug 24 '20 at 06:47
  • See https://stackoverflow.com/a/72568770/10669875 – wovano Nov 06 '22 at 14:48

3 Answers3

1

In CPython, ids relate to where in memory the string is stored. It does not indicate anything about mutability. How memory is used exactly is an internal implementation detail. You could of course do a deep dive into the internals of CPython's memory management to disentangle that in-depth, but that's not really useful. (Im)mutability can simply be demonstrated:

>>> foo = 'bar'
>>> baz = foo
>>> id(foo), id(baz)
(4402654512, 4402654512)
>>> foo += 'quux'
>>> print(foo, baz)
barquux bar
>>> foo[1] = 'o'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

Altering foo using += does not mutate baz, even though they used to refer to the same object. Altering a character directly though subscription (foo[1] = ...) does not work and raises an error. This demonstrates string immutability. How memory is allocated for this during execution is not really relevant.

deceze
  • 510,633
  • 85
  • 743
  • 889
1

It seems that the Python interpreter has some smarts to it. It detects that the old value of the variable sample is being discarded, and that it can reuse the space in which the old value was stored. Hence the old value and new value end up with the same id() even though they are different objects.

If you replaced each of the three sample += ... with

temp = sample
sample += ...

you'd see that you'd get a different id() each time. We're preventing Python from immediately reclaiming the space since another variable holds the old value.

Strings are immutable. There's no need for you to "test" it. Once a string is clearly dead, Python is free to re-use its space however it wants. You cannot expect ids to be unique across all objects both living and dead.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Frank Yellin
  • 9,127
  • 1
  • 12
  • 22
-1

id() gives the address in which a variable is stored. Of course, that will change every time when you alter that variable. The id() won't be same as you mentioned. It will change as said every time. And checking the address doesn't account that you are checking the immutability of strings.

For more clarification about strings, check the following link : https://www.python.org/dev/peps/pep-3137/

  • 1
    It actually does work the way OP demonstrates, at least in my Python version. Python is simply reusing the memory location if nothing else refers to it. – deceze Aug 24 '20 at 07:02