Search code examples
pythonpass-by-referencespace-efficiency

When reassigning a Python reference to itself, does it un-assign and re-assign, or do nothing?


def new_val(x):
    x['a'] = 5
    return x

b = {'a': 2}
b = new_val(b) # b re-assigned to ret val

Since dictionaries are mutable, b is a reference pointer to a dictionary, and we pass this pointer into the function new_val.

The reference to the dictionary doesn't change, but the dictionary's reference to 2 changes to 5.

The original variable b should now have 'a' map to 5. However, I'm wondering whether the reference to the dictionary (in other words, the pointer for variable b) ever changes.

We technically, 're-assign' the reference variable b to a reference that happens to be the same.

At a low level, what happens? Is this like a no-op, where some logic recognizes that the reference is the same, or does the reference actually get unassigned and reassigned?

Maybe a simpler example would be:

b = {}
b = b # At a low level, what does this line do?

Solution

  • b = b is not a no-op. The data held by previous b variable is reassigned to a new variable, which name is also b. So it does nothing but is not ignored.

    Don't take my word for it. Let's disassemble your last example instead:

    def f():
        b = {}
        b = b
    
    import dis
    
    print(dis.dis(f))
    
      2           0 BUILD_MAP                0
                  3 STORE_FAST               0 (b)
    
      3           6 LOAD_FAST                0 (b)
                  9 STORE_FAST               0 (b)
                 12 LOAD_CONST               0 (None)
                 15 RETURN_VALUE
    

    As you see there are 2 operations LOAD_FAST and STORE_FAST on b for that b = b line. They achieve nothing useful, yet they are executed.