By Ana Bell

This article, adapted from Get Programming: Learn to code with Python, discusses mutable and immutable objects in Python.

Save 37% off Get Programming with code fccbell at manning.com.

Immutable Objects

Most python objects (booleans, integers, floats, strings, and tuples) are immutable. This means that after you create the object and assign some value to it, you can’t modify that value.

Definition An immutable object is an object whose value cannot change.

What does this mean behind the scenes, in computer memory? An object created and given a value is assigned some space in memory. The variable name bound to the object points to that place in memory. Figure 1 shows the memory locations of objects and what happens when you bind the same variable to a new object using the expressions a = 1 and then a = 2. The object with value 1 still exists in memory, but you’ve lost the binding to it.


Figure 1. The variable named a is bound to an object with value 1 in one memory location. When the variable named a is bound to a different object with value 2, the original object with value 1 is still in memory, but you can’t access it anymore through a variable.


You can see the value of the memory location to which the object is assigned, using the id() function. Type the following in the console:

 
a = 1
id(a)
 

The value shown represents the location in memory of the object with value 1, accessed by the variable named a. Now, type the following:

 
a = 2
id(a)
 

Like before, the displayed value represents the location in memory of the object with value 2, accessed by the variable named a. Why are these values different if you’re using variable name a in both cases? We come back to the idea that the variable name is a name bound to an object – it points to an object; in the first case the variable pointed to the integer object with value 1 and then to the object with value 2. The id() function tells you the memory location of the object pointed to by the variable name, not anything about the variable name itself.

Objects of these types can’t be modified once created. Suppose you have the following lines of code, which are executed in the order shown. You initialize two variables, a and b, to two different objects with values 1 and 2, respectively. Then you change the binding of variable a, to a different object with a value of 3.

 
a = 1 
b = 2 
a = 3
 

Figure 2 shows the objects that exist in your program’s memory with each line of code

  • When you create the object with value 1, you bind the object to the variable named a.

  • When you create the object with value 2, you bind the object to the variable named b.

  • In the final line, you’re re-binding the variable named a to a completely new object, one whose value is 3.

The old object with a value of 1 may still exist in computer memory, but you lost the binding to it; you don’t have a variable name as a way to refer to it anymore.


Figure 2. Progression of binding variables to objects. On the left, a = 1 shows that the object 1 is at some memory location. In the middle, a = 1 then b = 2. Objects with values 1 and 2 are at different memory locations. On the right, a = 1 then b = 2 then a = 3. The variable named a is bound to a different object, but the original object still exists in memory.


Once an immutable object loses its variable handle, the Python interpreter may delete the object to reclaim the computer memory it took up, and use it for something else. Unlike some other programming languages, you (as the programmer) don’t have to worry about deleting old objects – Python takes care of this for you through a process called “garbage collection.”

Quick Check 1:

Draw out a diagram similar to the one in Figure 2 to show variables and objects that they point to (and any leftover objects) for the following sequence of statements.

 
sq = 2*2
ci = 3.14
ci = 22/7
ci = 3
 

The Need for Mutability

Once you lose the variable binding to an object, there’s no way to get back to that object. If you want the program to remember its value, you need to store its value in some temporary variable. Using a temporary variable to store values that you don’t need right now, but may need in the future, isn’t an efficient way of programming. It wastes memory and leads to cluttered code filled with variables that, for the most part, is never used again.

If immutable objects are objects whose value can’t change once created, a mutable object is an object whose value can change once created. Mutable objects are often objects that can store a collection of data. Lists (Python type list) and dictionaries (Python type dict) are examples of mutable objects.

For example, you can make a list of items you’ll need from the grocery store; as you decide what you need, you add them to the list. As you buy things, you remove them from the list. Notice that you’re using the same list and making modifications to it (crossing out or adding to the end) as opposed to having many lists in which you copy over items every time you want to make a change. As another example, you can keep your grocery needs in a dictionary that maps every item you need from the store to a number representing the quantity that you need.

Definition A mutable object is an object whose value can change.

Figure 3 shows what happens in memory when you bind variables to mutable objects. When you modify the object, you keep the same variable binding and the object at the same memory location’s directly modified.


Figure 3. On the left, you have a grocery list at some memory location. On the right, you add another item to your grocery list and the object at the same memory location is directly modified.


Mutable objects are more flexible when programming because you can modify the object without losing the binding to it.

First, a mutable object can behave the same way as an immutable object. If you rebind a sample grocery list to a variable a and check its memory location, you see that the memory location changes and the binding to the original list is lost.

 
a = ["milk", "eggs"]
id(a) 
a = ["milk", "eggs", "bread"]
id(a)
 

If you have the option to modify the original object directly without losing the binding to it, use operations that only work on mutable objects. In the code below, you append (add to the end of the list) one more item. The memory location of the object that the variable a is bound to remains unchanged. The behavior of the code below is shown in Figure 3.

 
a = ["milk", "eggs"]
id(a) 
a.append("bread")
id(a)
 

Mutable objects are useful in programing for several reasons.

First, you can store data, which is part of a collection (for example, lists of people or mappings of people to phone numbers), in an object and you can keep the object for use later on.

Once the object is created, you can add data to and remove data from the object itself, without creating a new object. Once you have the object, you can also modify elements in the collection by modifying the elements in the object itself instead of creating a new copy of the object with only one of its values modified.

Finally, you can rearrange data in the collection by keeping the same object and making the rearrangement in-place – an example is a list of people that you want to sort alphabetically.

With huge collections of data, it’d be inefficient to copy your collection into a new object every time you make a change to it.

Quick Check 2:

Would you use a mutable or an immutable type of object to store the following information?

  • Cities in a state

  • Your age

  • Group of items in a grocery store and their cost

  • Color of a car

That’s all for this article. If you’re interested in more, download the free first chapter of Get Programming and see this Slideshare presentation for a discount code