What you are seeing here is referred to in other languages as “value types” vs. “reference types”. If you’re interested, it’s a little dense but the relevant details of how Python stores objects are described here: Python 3.10 Data Model - Objects, Values, and Types
In short, Python values can be either mutable (their value can change) or immutable (their value is always the same). Integers and string values are immutable - when you create a variable pointing to a string or integer, then change the value stored in the variable, behind the scenes Python creates a new value and changes the variable to point to the new value. You can observe this with the built-in “id” function:
>>> a = 1
>>> id(a)
4491692336
>>> b = a
>>> id(b)
4491692336
>>> b = b + 1
>>> id(b)
4491692368
You can see that initially, the variables a
and b
are pointing to the same value - there is one instance of the value 1
being stored by Python, and both variables share it. However, when you change the value of variable b
by incrementing it, it does not also change the value for variable a
- instead, Python makes a new value and points b
to that, and leaves a
pointing to the old value.
The same thing happens with your dictionaries. Initially, your example variable b
does point to the same value in memory as dict1[3][1]
! However, as soon as you execute this statmement:
c = b + '...'
Python creates a new value for the result, and points c
to that value. When you then try to copy the variable back into the dictionary:
b = c
This points b
to the new value that was created, while dict1[3][1]
still points to the old value.
If you want to have multiple explicit references to the same value (several variables pointing to the same place) so that when when one variable changes, the other variables see the same new value, you will need to use a mutable container. Python’s list
and dict
are mutable containers, but you can also create a simple class to do the same thing:
>>> class Ref:
... def __init__(self, value):
... self.value = value
...
>>> a = Ref(1)
>>> b = a
>>> c = b
>>> a.value
1
>>> c.value = 2
>>> a.value
2
You can picture it a little like this (not a very good diagram):
var_a -\
---\
--\
var_b ----------> Ref.value ------> value
--/
---/
var_c -/