Python tutorials > Core Python Fundamentals > Data Types and Variables > What is mutability vs immutability?
What is mutability vs immutability?
In Python, understanding the difference between mutability and immutability is crucial for writing efficient and bug-free code. Mutability refers to the ability of an object to be changed after it is created, while immutability means that an object's state cannot be altered once it is created. This tutorial explores these concepts with examples.
Introduction to Mutability and Immutability
Immutability: An immutable object's value cannot be changed after it's created. If you try to modify it, a new object is created instead. Examples include integers, floats, strings, tuples, and frozensets. Mutability: A mutable object's value can be changed after it's created. The object's identity remains the same. Examples include lists, dictionaries, and sets.
Immutability in Action: Strings
Strings are immutable. When you concatenate strings, you're not modifying the original string; instead, you're creating a new string object. In the code, id()
returns the unique identifier of an object. You'll notice that the id
of my_string
changes after concatenation, indicating a new object was created.
my_string = "Hello"
print(id(my_string))
my_string = my_string + " World"
print(id(my_string))
Mutability in Action: Lists
Lists are mutable. You can add, remove, or modify elements within a list without changing its identity. In the code, the id()
of my_list
remains the same after appending an element, confirming that the original list object was modified.
my_list = [1, 2, 3]
print(id(my_list))
my_list.append(4)
print(id(my_list))
print(my_list)
Tuples: Immutable Sequences
Tuples are immutable sequences. You cannot modify their elements after creation. While you can create a new tuple by concatenating, the original tuple remains unchanged. The commented-out line demonstrates that directly modifying a tuple element results in a TypeError
.
my_tuple = (1, 2, 3)
# Attempting to modify a tuple will raise an error:
# my_tuple[0] = 4 # This will cause a TypeError
new_tuple = my_tuple + (4,)
print(new_tuple)
Dictionaries: Mutable Key-Value Pairs
Dictionaries are mutable. You can add, remove, or modify key-value pairs without changing the dictionary's identity. The id()
of my_dict
remains the same after adding a new key-value pair, indicating that the original dictionary was modified.
my_dict = {'a': 1, 'b': 2}
print(id(my_dict))
my_dict['c'] = 3
print(id(my_dict))
print(my_dict)
Concepts behind the snippet
Understanding mutability and immutability is fundamental to understanding how Python handles data. Mutable objects can be changed in place, which can be more efficient in terms of memory usage and speed when performing many operations. However, it also means that multiple variables pointing to the same mutable object will all be affected by changes to that object. Immutable objects guarantee that their value will never change, leading to simpler reasoning about code and better thread safety.
Real-Life Use Case Section
Consider a scenario where you're working on a multi-threaded application. If multiple threads access and modify a mutable object (like a list) simultaneously, it can lead to race conditions and unpredictable behavior. Using immutable data structures (like tuples or frozensets) in such cases ensures thread safety, as their values cannot be changed concurrently. Another example is caching. Immutable objects can be safely cached without worrying about them being modified unexpectedly.
Best Practices
copy.copy()
(shallow copy) or copy.deepcopy()
(deep copy) to avoid unintended modifications to the original object.
Interview Tip
During interviews, be prepared to explain the difference between mutable and immutable data types in Python, provide examples of each, and discuss the implications for memory management and program behavior. You should also be able to explain how to copy mutable objects to avoid unintended side effects.
When to use them
Memory footprint
Mutable objects, when modified in place, generally have a smaller memory footprint compared to creating new immutable objects for each modification. However, the trade-off is the potential for unexpected side effects and the need for careful management. Immutable objects may lead to higher memory consumption due to the creation of new objects, but they offer greater predictability and ease of debugging.
Alternatives
For mutable lists, there are immutable alternatives like tuples. Instead of directly modifying a list, consider creating a new one. For sets, there are frozensets which are immutable. For dictionaries, although there isn't a direct immutable equivalent, you can simulate immutability by creating a new dictionary each time you want to 'modify' it, or use specialized libraries that offer immutable dictionary implementations (though these are less common).
Pros of Immutability
Cons of Immutability
FAQ
-
Why are strings immutable in Python?
Strings are immutable for several reasons, including optimization of memory allocation and improved performance. Since strings are often used as keys in dictionaries, immutability guarantees that their hash values remain constant.
-
How can I modify a tuple?
You cannot directly modify a tuple. However, you can create a new tuple based on an existing one using concatenation or slicing.
-
What is the difference between `copy.copy()` and `copy.deepcopy()`?
copy.copy()
creates a shallow copy, which means it creates a new object but references the same internal objects as the original.copy.deepcopy()
creates a deep copy, which means it creates a new object and recursively copies all the internal objects as well. For mutable objects containing other mutable objects,deepcopy()
is often preferred to avoid unintended side effects.