Additionally, to the excellent answers by @Thomas Weller, and @Barmar, you can see how the objects are stored in memory by using id() for each of the objects once they are mapped to a variable.
a = [1,2,3]
hex(id(a))
'0x1778bff00'
Furthermore, as @Max points out in their comment, this list type object is also just storing multiple int objects in this case which have their own memory location. These can be checked by the same logic -
[hex(id(i)) for i in a]
['0x10326e930', '0x10326e950', '0x10326e970']
Now, if you create another list object b which stores the 3 int objects and the previously defined list object a, you can see these refer to the same memory locations -
b = [1,2,3,a]
[hex(id(i)) for i in b]
['0x10326e930', '0x10326e950', '0x10326e970', '0x1778bff00']
And this also shows the behavior of self-referencing objects, such as an object that stores itself. But for this b has to be defined once initially already, since without a memory allocated to b you wont be able to store it into another object (in this case, store it in itself)
b = [1,2,3,b]
hex(id(b)) #'0x1590ad480'
[hex(id(i)) for i in b]
['0x10326e930', '0x10326e950', '0x10326e970', '0x17789f380']
However, if you map the same list of elements of 2 different variables, while the int objects still point to the same memory, these 2 variables have different memory locations, as expected -
d = [1,2,3]
e = [1,2,3]
print('d ->',hex(id(d)))
print('e ->',hex(id(e)))
print('elements of d ->',[hex(id(i)) for i in d])
print('elements of e ->',[hex(id(i)) for i in e])
d -> 0x16a838840
e -> 0x16a37d880
elements of d -> ['0x10326e930', '0x10326e950', '0x10326e970']
elements of e -> ['0x10326e930', '0x10326e950', '0x10326e970']
Redefining a variable with the same elements will keep the same int objects these point to, but the memory location for the variable changes.
d = [1,2,3]
print('old d ->',hex(id(d)))
d = [1,2,3]
print('new d ->',hex(id(d)))
old d -> 0x16a5e7040
new d -> 0x16a839080