Executing integers that are mutable would be very controversial for how we are used to working with them.
Consider this piece of code:
a = 1
After completing these assignments, we expect that the value 1 and b will have the value 3. The add operation creates a new integer value from the integer stored in a and the instance of the integer 2. If the add operation just took the integer in and just changed it , then both a and b will have a value of 3.
So, we expect that arithmetic operations will create new values for their results - do not change their input parameters.
However, there are cases where a mutation in the data structure is more convenient and efficient. Suppose that at the time list.append(x) did not change list , but returned a new copy of list with the addition of x . Then a function like this:
def foo(): nums = [] for x in range(0,10): nums.append(x) return nums
just return an empty list. (Remember - here nums.append(x) does not change nums - it returns a new list with the addition of x . But this new list is not saved anywhere.)
We need to write the foo procedure as follows:
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 to about 2.6 or maybe 2.5.)
In addition, each time we assign nums = nums.append(x) , we will copy a list that grows in size, resulting in a quadratic behavior. For these reasons, we create lists of mutable objects.
The consequence of creating mutable lists is that after these statements:
a = [1,2,3] b = a a.append(4)
list b has changed to [1,2,3,4] . This is what we live with, despite the fact that it still turns us on from time to time.