Mutable vs. Immutable Objects

Lisa Olson
5 min readMay 9, 2018

--

OOP

Python is built around objects. The idea is that you have blocks of things you want to accomplish within one reusable object, hence the known phrase, ‘Object-Oriented Programming’ or OOP. Being an object-oriented language, Python is set up to be used to organize patterns to accomplish entire brackets of things rather than separate files systematically or sequentially.

Objects

So what is an object exactly? An object is an instance of a class. Classes are the structure that the objects and instances are built in. So picture a wax figure. The class would be the mold that you pour the wax into. The object conforms to the shape of the class it’s in.

If we were to create a class, it would look like this:

class ClassName:    pass

An object is an instance of a class. I’ll show you what that would look like in the case of a class named crayon.

class Crayon:    pass
blue = Crayon()

That initializes the object blue as an instance of the class by setting it equal to Crayon().

If we had anything else inside of our class, Crayon, it would be available to the object blue we just created. For example, if our class looked like this :

class Crayon:    def color_things(self):        print(“coloring everything blue”)

We could use our object like this:

blue.color_things()

Ids and Types

Now that you have an idea of how classes and objects work, we can talk briefly about ids and types. An Id is the identity of an object; it’s the address of the object in memory. An id is always unique within the lifetime of it’s object. Type returns the type of an object.

Both of these things are important because depending on the type in Python, the id will either stay the same or change. The memory addresses change depending on the data type.

Mutable vs. Immutable

Some objects are immutable and others are mutable. Mutable objects can be changed after creation. Examples of mutable objects are lists, sets, and dictionaries. Immutable objects cannot be changed after creation, examples being integers, floats, booleans, strings, tuples and unicode.

Let’s look at some examples.

First we assign a to equal 3 by using a single equal sign. This is called assignment. We do the same with variable b.

>>> a = 3
>>> b = 3
>>> type(a)
<class 'int'>
>>> type(b)
<class 'int'>

We’ve set a and b to equal the same integer value. Since integers are immutable, a and b are actually stored at the same memory address. We can see that by checking the id.

>>> id(a)
4307789712
>>> id(b)
4307789712

Let’s look at an immutable example.

>>> a = [1, 2, 3, 4]
>>> b = [1, 2, 3, 4]
>>> type(a)
<class 'list'>
>>> type(b)
<class 'list'>

We’d expect these to be at different memory address because lists are mutable. We can see that confirmed below.

>>> id(a)
4316334920
id(b)
4316334856

== vs. is

This brings up the difference between variables being identical versus linked to the same object. Using ‘==‘ and ‘is’, we can see the difference. ‘==‘ shows us whether the values are identical. Using ‘is’, we can see whether they’re linked to the same object.

So, as in the first example where we had :

>>> a = 3
>>> b = 3
>>> a is b
True
>>> a == b
True

This is to be expected since a and b are pointing to the same address and also are holding the same value. However, in the second example, we’ll see things change a bit.

>>> a = [1, 2, 3, 4]
>>> b = [1, 2, 3, 4]
>>> a is b
False
>>> a == b
True

Even though the values are the same, they’re pointing to different objects since list is a mutable data type.

Aliases and References

We can look at some other interesting examples when we bring up aliasing and referencing. An alias is when one variable’s value is assigned to another variable. Variables are just names that store references to values so if the data is immutable, aliasing doesn’t matter. The data won’t change either way, so it doesn’t matter how many times it’s referred to. If the data is mutable, however, things can get confusing.

We’ll start with two different values.

>>> a = [“a”, “b”, “c”]
>>> b = [1, 2, 3]
>>> a is b
False

False is to be expected. But now, we’ll set a = b

>>> a = b

This means a now refers to b’s location in memory of an object. This is called a reference, since it’s referencing b.

>>> print(a)
[1, 2, 3]
>>> print(b)
[1, 2, 3]

So the values are now the same since a is referencing b. Let’s start changing some values and see what happens.

>>> b += [5]>>> print(a)
[1, 2, 3, 4, 5]
>>> print(b)
[1, 2, 3, 4, 5]

The changes are reflected in both variable a and b. But what if we now make changes to a?

>>> a = a + [8]>>> print(a)
[1, 2, 3, 5, 8]
>>> print(b)
[1, 2, 3, 5]

The variable a’s changes are reflected and held, but b’s changes are not reflected. Since a is referencing b, a is impacted by b, but b is not impacted by a.

This is why it matters so much whether you’re dealing with mutable or immutable data types. If you’re not extremely careful with assignment, aliasing, and referencing, you can run into problems quickly.

How arguments are passed to functions

Unlike other languages, Python uses something known as ‘Call by Object’ to pass arguments to functions. When passing immutable arguments, the object reference is passed to the function parameters. This makes sense because they’re immutable, so they can’t be changed inside/outside of the function. When it comes to mutable arguments however, they’re also passed as object references but they can be changed in place of the function.

Depending on the scope, the id of the variable will change.

For example :

>>> a = 9
>>> id(a)
4307789904
>>> def func(a):
a = 15
print(id(a))
>>> func(15)
4307790096
id(a)
4307789904

Even though the value was changed inside of the function, the id of the global a is still preserved.

Hope this was a helpful recap of objects, classes and immutable vs. mutable objects! Happy coding!

--

--

Lisa Olson

Front End Developer. Passionate about everything I do. How we spend our days is how we spend our lives.