News

Immutable vs Mutable: Unveiling the Nature of Main Tuple 

6 min read
Rear view of a man writing program code on a computer

The exciting world of Python presents a plethora of variable types, each with its unique subtleties and functionalities. In general terms, Python variables can be pigeonholed into one of two broad categories: mutable and immutable.

Mutable vs. Immutable: A Refresher

Let’s take a brief detour to recall the difference between mutable and immutable data types, as we laid the groundwork in our previous piece, ‘The Essentials of Mutable and Immutable Data Types’.

  • Mutable Data Types: These Python elements offer the flexibility of being modified post-creation. In other words, you can tweak and adjust the elements of mutable objects without having to construct a new one from scratch;
  • Immutable Data Types: On the contrary, immutable Python elements firmly maintain their state post-instantiation. These objects are ‘read-only’ or non-changeable, meaning once you create an immutable object, it’s content cannot be altered.

A salient example of an immutable object is a tuple.

Tuples: Immutable, But Seemingly Mutable?

Tuples are a fascinating part of Python and often used in programming due to their immutable nature. But as we will discuss in this article, these tuples may exhibit characteristics that suggest mutability.

Unraveling the Truth About Tuples

Tuples in Python are known to be immutable. They are among the variety of data types that, once created, maintain their state and content. This means that the elements of the tuple cannot be changed.

But is this the whole truth? Can tuples appear to change their state? The answers to these questions may surprise both novice and experienced Python programmers.

Delving into Python Tuples

The formation of tuples in Python is facilitated by the embedding of elements within parentheses ( ) and their retrieval can be done through the use of square brackets [ ]. A simple example would be:

Defining a tuple

tuple1 = (1, 2, 3)
# Accessing the first element
tuple1[0]

The output will affirmatively display the first element of the tuple, which is 1 in this case. However, due to tuple’s immutable nature, attempts to alter its elements post-creation would inevitably result in errors. Therefore, running tuple1[0] = 0 will output an error, confirming the immutability of the tuple.

Tuples, in their versatile nature, aren’t confined to housing just numerical values, but can hold a vast array of other data types including lists. This presents another layer of intrigue to the Python tuple:

Creating a tuple with a list

list1 = [1, 2, 3]
tuple2 = (1, list1)
tuple2[1]

The above code will output [1, 2, 3] as expected. However, trying to mutate a list within a tuple would yield surprising results:

Changing an element in the list within the tuple

tuple2[1][0] = 0

This operation, contrary to our initial understanding of tuples, executes flawlessly. The explanation lies in the fact that tuples don’t literally store the objects but rather their references. Changing a list doesn’t alter its identity, which is why the operation works:

List identity remains the same post-mutation

list2 = [1, 2, 3]
id(list2)
list2[0] = 0
id(list2)

In both instances, you’d notice that the identity remains the same, reinforcing our explanation.

The identity of the objects referenced in the tuple doesn’t change even if we mutate the list or append new items. However, this isn’t the case for other immutable data types like integers, which form entirely new objects upon mutation. Hence, mutating an integer within a tuple will raise an exception.

The concept of references clarifies further when the same tuple is assigned different names:

Assigning the same tuple to different variables

var3 = (1, list1)
var4 = var3
var3 is var4
var4[1] is list1

In both instances, the Python interpreter returns a True, indicating that both the variables are referencing the same tuple and list respectively.

When we mutate the list via any of these variables (be it var3, var4 or list1), the change will be distinctly noticeable in all other variables:

Changing the list updates it in all associated variables

var3[1][0] = 0
list1
var4[1]

Each of these operations will output [0, 2, 3]. The changes are mirrored across all the variables.

Creating a new variable for the list

var5 = (1, [1, 2, 3])
list2 = var5[1]
print(list2)
list2[0] = 0
var5

In the above case, var5 will now display as (1, [0, 2, 3]), once again confirming that all labels or variables pointing to the same list will reflect any changes made to that list.

Hands on laptop keyboard writing code

Leveraging Tuples as Key to Python Dictionaries

Python dictionaries are versatile data structures that allow users to store key-value pairs. These key-value pairs are indexed by their keys, which allows for efficient data retrieval and organization. Among the many useful features of Python dictionaries, one is the ability to use any immutable datatype, including tuples, as keys.

For example, here is how you might create a dictionary using tuples as keys:

Defining tuples

tuple1 = (1, 2)
tuple2 = (4, 5)

Using tuples as keys in a dictionary

dict1 = {tuple1: 'First Tuple', tuple2: 'Second Tuple'}

Accessing a value using a tuple key

print(dict1[1, 2])

Running the above script, you will see ‘First Tuple’ printed to the console, indicating that the dictionary value was successfully accessed using the tuple key.

However, it is important to note that while tuples are immutable, they can still contain mutable elements. If a tuple contains a mutable object (like a list), it will not be usable as a dictionary key. Consider the following example:

Creating a tuple with a list

tuple3 = (1, [1, 2, 3])

Using tuples as keys in a dictionary

dict2 = {tuple1: 'First Tuple', tuple3: 'Second Tuple'}

Executing this script will yield a TypeError with a message indicating that ‘list’ is an ‘unhashable’ type. This is because dictionary keys must be immutable, and while the tuple itself is immutable, it contains a mutable list.

Therefore, caution must be exercised when using tuples as dictionary keys. Make sure that the tuples are composed only of immutable objects to ensure that they can be hashed correctly and used as keys without raising errors.

Integrating Python with Arduino: A Synergy of Flexibility and Control

In the odyssey through Python’s variable types, an intriguing crossroad emerges where Python intersects with Arduino, a realm where mutable and immutable types gain new dimensions of utility. Arduino, the open-source electronics platform, becomes a canvas for Python’s scripting prowess, allowing programmers to infuse life into hardware projects with the nuanced control Python offers.

The Convergence of Python and Arduino: Mutable and Immutable in Action

When Python scripts are used to program Arduino boards, the distinction between mutable and immutable types takes on practical significance. Consider an Arduino project where sensor data is collected and manipulated. Here, mutable types in Python, like lists or dictionaries, can be dynamically altered to accommodate streaming data, showcasing their adaptability in real-time applications.

Simultaneously, the immutable nature of tuples in Python can be leveraged to maintain consistent reference points or settings within an Arduino project. For instance, tuples can represent fixed configurations or coordinates in a robotic arm’s movement, ensuring stability and predictability where it is paramount.

Arduino Python: Bridging Hardware and Software

The fusion of Arduino with Python illustrates the harmony between hardware control and software logic. Python scripts, known for their readability and simplicity, become the guiding force for Arduino’s physical computing capabilities. This symbiosis not only expands the horizons of what can be achieved with Python’s variable types but also opens up a playground for creative experimentation, where the tangible world meets the algorithmic precision of Python.

Wrapping Up

Embracing the complex world of Python’s mutable and immutable types can be a challenging yet rewarding endeavour. Familiarizing oneself with these subtleties can lead to the creation of robust and efficient code, reducing possibilities of unexpected bugs. The intellectual sojourn unravels intricate facets like the propensity to use tuples as default arguments over lists in many Python packages. With these deeper nuances demystified, you are one step closer to becoming a more seasoned and proficient Python programmer.