Python’s Mutable and Immutable Objects
Python is currently one of the most popular languages used today in software development. In the 2016 Github Octoverse, Python ranks third in all programming languages on Github’s Octoverse (https://octoverse.github.com).
The language is easy-to-learn and use. But, let’s start with the basics. You will soon find out that everything in Python is an object. A variable is an object, a string is an object, a integer is an object, even math comparator symbols are objects (<, >, =, etc signs) which you can redefine (or overload).
One of the unique aspects of Python is that variables can be stored in a couple of ways: stored separately in different memory addresses (Panel A) or aliased (shared with another variable) as seen in the image below (Panel B).
Since this can cause obvious confusion, we need a way to differentiate between the two different types of objects. How? Let’s use the Python REPL by typing
python3 in a terminal window, then check whether the VALUES of a and b match, you can use the
>>> a == b
To test whether two variables refer to the same object use the
>>> a is b
Or, another simple solution is to use
id() and type()
To find the memory address of a variable, use
id([VarName]). In the image above, you see that both variables hold the value of
1 in the memory address
10055552 and that both a and b are integers. Both variables are actually labels that point to a specific integer, 1, in an array of integers that python keeps in memory. The values from -5 to 256 are pre-allocated (stored) in an array in order to save processing time. These range of integers are arbitrarily determined to be the more commonly-used integers. You can think of these variables as labels to the integers and each of these special integers have a special counter to know how many variables use that value.
Numbers outside the pre-allocated range are newly-allocated and in a different part of memory.
type() is a built-in command that tells you what class the variable or value is. Some of the types that are in Python include Mutable objects (list, dict, set, bytearray, and custom classes/objects) and Immutable objects (int, float, str, tuple, complex, bytes, frozenset).
Python has designated certain data types to be mutable. Mutable variables can change its value and can change their values in-place (without making a copy of itself first). These include
list, set, dict, bytearray, and user-defined
custom classes/objects. These type of variables support assignment operations and in-place assignments.
The other group of objects include immutable types, such as
int, float, str, tuple, complex, bytes, and
frozenset. At times it is useful to protect the values of data or data structures, and immutable types serve this need. Attempts to change its value directly will generate an error. However, the variable can be completely reassigned.
It is also interesting to note if that a string is treated differently by the Python Memory Manager if it has white space in it. If it does, then it’s allocated separately. If the string has no white-space, other variables that have the same value will point to the same memory location as the original variable.
Also, strangely enough, an immutable tuple cannot be changed. However, if the element(s) inside the tuple are mutable, then the element(s) can be changed.
Why is Mutability and Immutability Important?
When programming, it’s important to keep in mind how the computer is processing your code. If memory is limited or processing speed is important, say, in BigData applications, then you will want to optimize your code. For example,
But, it can be expensive to create because strings are immutable and concatenating strings must allocate memory for a new string and copy the contents. In the above code, the resulting string is created from separate strings. It may be more Pythonic to use one of the methods below because it creates the final string with less objects by appending. Appending to a list (in most cases) requires no allocation. Immutable objects are fundamentally expensive to change, but mutable objects are cheap.
How arguments are passed to functions and what does that imply for mutable and immutable objects
Python is neither strictly “call-by-reference” nor “call-by-value”. In Python a variable is not an alias for a location in memory. Rather, it is simply a binding to a Python object.
Immutable arguments act like C’s “by value” mode
Objects such as integers and strings are passed by object reference (assignment), but since you can’t change immutable objects in place anyhow, the effect is much like making a copy.
Mutable arguments act like C’s “by pointer” mode
Objects such as lists and dictionaries are passed by object reference too, which is similar to the way C passes arrays as pointers — mutable objects can be changed in place in the function, much like C arrays.
So, go ahead and try Python yourself, which can be easily done by playing with Python’s REPL (interactive interpreter). See how Python manages its objects. It’s a powerful language, and it has its idiosyncrasies.