Programming
Mutable vs. Immutable Objects in Python: Understanding and Performance
In Python, every value is an object. These objects are classified as either mutable or immutable, a distinction that's crucial for understanding how Python handles data and memory, and for writing efficient, error-free code. This concept isn't unique to Python; it applies to many programming languages.
Ryan McBride
Ryan McBride
alt

Source: Ales Krivec on Unsplash

1. Immutable Objects

Immutable objects are those whose state cannot be changed after they are created. If you try to modify an immutable object, you're actually creating a new object in memory.

1.1. Examples of Immutable Objects in Python

  • Strings (str): Strings are a prime example of immutability.
  • Numbers (int, float, complex): Numerical values cannot be changed in place.
  • Tuples (tuple): Like strings, tuples are ordered sequences that cannot be modified.
  • Booleans (bool): True and False are immutable.
  • Frozen Sets (frozenset): Immutable versions of sets.

1.2. Immutability in Action: Strings


    my_string = "hello"
    print(f"Original string: {my_string}, id: {id(my_string)}")

    my_string = "world"  # Reassignment creates a new string object
    print(f"Modified string: {my_string}, id: {id(my_string)}") # Notice the different id

    # Attempting to modify a string directly results in an error
    # my_string[0] = 'H'  # TypeError: 'str' object does not support item assignment
   

When you reassign my_string, you're not changing the original "hello" string. Instead, a new string object "world" is created, and my_string now points to this new object in memory. The id() function confirms that the memory address has changed.

2. Mutable Objects

Mutable objects, on the other hand, can be modified after they are created. Changes made to a mutable object are done in place, without creating a new object.

2.1. Examples of Mutable Objects in Python

  • Lists (list): Ordered sequences that can be modified.
  • Dictionaries (dict): Key-value pairs that can be changed.
  • Sets (set): Unordered collections of unique items that can be modified.

2.2. Mutability in Action: Lists


    my_list = [1, 2, 3]
    print(f"Original list: {my_list}, id: {id(my_list)}")

    my_list[0] = 10  # Modifying the list in place
    print(f"Modified list: {my_list}, id: {id(my_list)}") # The id remains the same
   

In this case, the id() function shows that the memory address of my_list remains the same after the modification, demonstrating that the list was changed in place.

3. Performance Implications

The distinction between mutable and immutable objects has significant performance implications, especially when dealing with operations that involve repeated modifications.

3.1. String Concatenation: An Inefficiency Example

Repeatedly concatenating strings using the + operator can be inefficient because each concatenation creates a new string object. For a large number of concatenations, this can lead to excessive memory allocation and performance overhead.


    import time

    start_time = time.time()
    result = ""
    for i in range(100000):
     result += str(i)  # Inefficient string concatenation
    end_time = time.time()
    print(f"String concatenation time: {end_time - start_time:.4f} seconds")

    start_time = time.time()
    result_list = []
    for i in range(100000):
     result_list.append(str(i)) # Append to a list
    result = "".join(result_list) # Join the list elements
    end_time = time.time()
    print(f"List append and join time: {end_time - start_time:.4f} seconds")
   

The output clearly demonstrates that using a mutable list to accumulate the string parts and then joining them is significantly faster than repeated string concatenation.

3.2. Choosing the Right Data Structure

Understanding mutability helps you choose the right data structures for optimal performance. If you need to modify a sequence frequently, a list is generally more efficient than a tuple. If you need to ensure that data remains unchanged, a tuple is a better choice.

4. Comparison to Other Languages (Java)

The concept of mutability and immutability is not unique to Python. For example, in Java:

  • The String class is immutable, similar to Python strings.
  • The StringBuffer and StringBuilder classes provide mutable alternatives for efficient string manipulation.

5. Conclusion

The mutability or immutability of an object type affects how operations are performed and how memory is managed. Understanding this distinction is crucial for writing efficient, correct, and performant code.