Mutation in Python

  1. Mutation occurs when we change the value stored at a location. The simplest locations are variables.

    >>> x = 123
    >>> x
    123
    >>> y = x
    >>> y
    123
    >>> y = 456
    >>> y
    456
    >>> x
    123
    >>>
    
  2. However we can also refer to locations in structures such as lists, tuples, etc.

    >>> x = [5,4,3,2,1]
    >>> x[2]
    3
    >>> y = (5,4,3,2,1)
    >>> y[3]
    2
    >>>
    
  3. Remember that lists and dictionaries are mutable whereas tuples and strings are not.
  4. We can mutate a value within a mutable structure:

    >>> number_string = 'zero one two three four five six seven eight nine'
    >>> number_list = number_string.split()
    >>> number_list
    ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
    >>> number_list[5]
    'five'
    >>> number_list[5] = 'vijf'
    >>> number_list
    ['zero', 'one', 'two', 'three', 'four', 'vijf', 'six', 'seven', 'eight', 'nine']
    
  5. But note that structure is shared. Here nummer_lijst is assigned to the same structure as number_list. This meal that when part of number_list is mutated, that same part of nummer_lijst is also mutated.

    >>> number_list = number_string.split()
    >>> nummer_lijst = number_list
    >>> number_list
    ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
    >>> nummer_lijst
    ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
    >>> number_list[5] = 'vijf'
    >>> number_list
    ['zero', 'one', 'two', 'three', 'four', 'vijf', 'six', 'seven', 'eight', 'nine']
    >>> nummer_lijst
    ['zero', 'one', 'two', 'three', 'four', 'vijf', 'six', 'seven', 'eight', 'nine']
    >>>
    
  6. This can be pictured as follows

    >>> l1 = [1,2,3]
    >>> l2 = l1
    >>> l3 = [1,2,3]
    >>> l1[2] = 'three'
    >>> l1
    [1, 2, 'three']
    >>> l2
    [1, 2, 'three']
    >>> l3
    [1, 2, 3]
    

    lists.png

  7. This behaviour holds not only for lists but for all mutable Python structures and for structures in structures in structures…
  8. Note however that the + and * operators on sequences always produce new sequences which do not share structure with their operands

    >>> l = [1,2,3]
    >>> m = l + l
    >>> m
    [1, 2, 3, 1, 2, 3]
    >>> n = l * 4
    >>> n
    [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
    >>> l[0] = 8
    >>> m
    [1, 2, 3, 1, 2, 3]
    >>> n
    [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
    >>> l
    [8, 2, 3]
    
  9. You can check whether two structures are equal using the == operator, and whether they are identical using the is operator. Identity is a stricter notion that equality. If two objects are identical they are always equal.

    >>> l1 = [1,2,3]
    >>> l2 = l1
    >>> l3 = [1,2,3]
    >>> l1 is l2
    True
    >>> l1 is l3
    False
    >>> l1 == l2
    True
    >>> l1 == l3
    True
    
  10. In fact, each Python object has a unique identity which you can access using the id function

    >>> id(l1)
    140737352275080
    >>> id(l2)
    140737352275080
    >>> id(l3)
    140737352276160
    

Author: Breanndán Ó Nualláin <o@uva.nl>

Date: 2025-02-10 Mon 14:45