can someone explain the concept of "strings (or whatever) being immutable"

Steven D'Aprano steve at pearwood.info
Tue Jun 3 03:46:26 EDT 2014


On Mon, 02 Jun 2014 21:06:37 -0800, Deb Wyatt wrote:

> """a_string = "This is a string"
> a_string is pointing to the above string
> 
> now I change the value of a_string

This is where English can lead us astray. "Change the value of a_string" 
can mean two different things. An analogy may help make it clear.

Some people give their car a name. Suppose I call my car "Vera". I might 
then "change the value of Vera" by replacing the engine with a more 
powerful one, installing superchargers, giving the car a new paint job, 
and replacing the tape desk with an MP3 player. The name "Vera" still 
refers to the same physical car, but now it is quite different from how 
it was before. This is equivalent to modifying a mutable value (like a 
list) in-place.

On the other hand, I might instead trade in my car for a newer model, and 
transfer the name with it. (I'm very unimaginative when it comes to names 
-- if I had children, they would all be called Chris, and all my pets are 
called Fluffy -- even the goldfish.) Whereas before Vera referred to a 
blue Toyota, now it refers to a red Ford. This is equivalent to replacing 
the string with a new string.

In Python terms, we call that "re-binding". "Binding" is another term for 
assignment to a name. All of these things are binding operations:

import math
from random import random
x = 23
my_string = my_string.upper()


while these are mutation operations which change the value in-place:

my_list[0] = 42
my_list.append(None)
my_list.sort()
some_dict['key'] = 'hello world'
some_dict.clear()

Only mutable objects can be changed in place: e.g. lists, dicts, sets. 
Immutable objects are fixed at creation, and cannot be changed: strings, 
ints, floats, etc.

Some objects fall into a kind of grey area. Tuples are immutable, but 
tuples can include mutable objects inside them, and they remain mutable 
even inside the tuple.

t = (1, 2, [])  # tuple is fixed
t[2] = [1]  # fails, because you're trying to mutate the tuple
t[2].append(1)  # succeeds, because you're mutating the list inside t


> a_string = "This string is different" I understand that now a_string is
> pointing to a different string than it was before, in a different
> location.
> 
> my question is what happens to the original string??  Is it still in
> memory somewhere, nameless? """
> That was just the first question.  What does immutable really mean if
> you can add items to a list? and concatenate strings?  I don't
> understand enough to even ask a comprehensible question, I guess.

No, it's an excellent question!

When an object is *unbound*, does it float free in memory? In principle, 
it could, at least for a little while. In practice, Python will recognise 
that the string is not being used for anything, and reclaim the memory 
for it. That's called "garbage collection". There are no promises made 
about when that happens though. It could be instantly, or it could be in 
an hour. It depends on the specific version and implementation of Python.

(CPython, the standard version, will almost always garbage collect 
objects nearly instantly. Jython, which is Python on the Java Virtual 
Machine, only garbage collects objects every few seconds. So it does 
vary.)


In the case of lists, we've seen that a list is mutable, so you can 
append items to lists. In the case of string concatenation, strings are 
immutable, so code like this:

s = "Hello"
s += " World!"

does not append to the existing string, but creates a new string, "Hello 
World!", and binds it to the name s. Then the two older strings, "Hello" 
and " World!" are free to be garbage collected.



-- 
Steven



More information about the Python-list mailing list