Why are integers immutable in Python?

Izzo picture Izzo · May 31, 2016 · Viewed 17.9k times · Source

I understand the differences between mutable and immutable objects in Python. I have read many posts discussing the differences. However, I have not read anything regarding WHY integers are immutable objects.

Does there exist a reason for this? Or is the answer "that's just how it is"?

Edit: I am getting prompted to 'differentiate' this question from other questions as it seems to be a previously asked question. However, I believe what I'm asking is more of a philosophical Python question rather than a technical Python question.

It appears that 'primitive' objects in Python (i.e. strings, booleans, numbers, etc.) are immutable. I've also noticed that derived data types that are made up of primitives (i.e. dicts, lists, classes) are mutable.

Is that where the line is drawn whether or not an object is mutable? Primitive vs derived?

Answer

ErikR picture ErikR · May 31, 2016

Making integers mutable would be very counter-intuitive to the way we are used to working with them.

Consider this code fragment:

a = 1       # assign 1 to a
b = a+2     # assign 3 to b, leave a at 1

After these assignments are executed we expect a to have the value 1 and b to have the value 3. The addition operation is creating a new integer value from the integer stored in a and an instance of the integer 2. If the addition operation just took the integer at a and just mutated it then both a and b would have the value 3.

So we expect arithmetic operations to create new values for their results - not to mutate their input parameters.

However, there are cases where mutating a data structure is more convenient and more efficient. Let's suppose for the moment that list.append(x) did not modify list but returned a new copy of list with x appended. Then a function like this:

def foo():
  nums = []
  for x in range(0,10):
    nums.append(x)
  return nums

would just return the empty list. (Remember - here nums.append(x) doesn't alter nums - it returns a new list with x appended. But this new list isn't saved anywhere.)

We would have to write the foo routine like this:

def foo():
  nums = []
  for x in range(0,10):
    nums = nums.append(x)
  return nums

(This, in fact, is very similar to the situation with Python strings up until about 2.6 or perhaps 2.5.)

Moreover, every time we assign nums = nums.append(x) we would be copying a list that is increasing in size resulting in quadratic behavior. For those reasons we make lists mutable objects.

A consequence to making lists mutable is that after these statements:

a = [1,2,3]
b = a
a.append(4)

the list b has changed to [1,2,3,4]. This is something that we live with even though it still trips us up now and then.