Hiprup

What is the difference between mutable and immutable objects?

Every Python value is an object, and every object is either mutable (its state can change after creation) or immutable (its state is fixed for life). The distinction affects how assignment, function arguments, hashing, and aliasing behave.

Which is which:

  • Immutableint, float, complex, bool, str, bytes, tuple, frozenset, range, None.

  • Mutablelist, dict, set, bytearray, most user-defined classes, many standard-library objects (deque, array.array).

What mutability actually means: for an immutable object, any “modification” creates a new object — the original is unchanged.

# Immutable - creates new object
s = 'hello'
print(id(s))
s += ' world'
print(id(s))  # Different id! New object created

# Mutable - modifies in place
lst = [1, 2, 3]
print(id(lst))
lst.append(4)
print(id(lst))  # Same id! Same object modified

# Aliasing with mutable objects
a = [1, 2, 3]
b = a           # Both point to same list
b.append(4)
print(a)        # [1, 2, 3, 4] — a is affected!

# Mutable default argument GOTCHA
def add_item(item, lst=[]):  # DANGEROUS!
    lst.append(item)
    return lst

print(add_item('a'))  # ['a']
print(add_item('b'))  # ['a', 'b'] — same list reused!

# Fix: use None as default
def add_item_fixed(item, lst=None):
    if lst is None:
        lst = []
    lst.append(item)
    return lst

String concatenation creates a new object (different id). List append modifies in place (same id). Aliasing: a and b reference the same list — modifying through b affects a.

The mutable default argument bug: the default list is created once and shared across all calls. The fix uses None and creates a new list inside the function.

The mutable default argument gotcha is one of the most asked Python questions. Show the bug AND the fix (None default).

Know which types are mutable vs immutable. The aliasing issue (two names, one object) is equally important.

What is the difference between mutable and immutable objects? | Hiprup