Reputation: 51
I am using repl.it
for python3 -
Here is a sequence of assignments I did
x34=20
x34
=> 20
hex(id(x34))
=> '0x7fdb5d318960'
x34=30
hex(id(x34))
=> '0x7fdb5d318aa0'
hex(id(x34))
=> '0x7fdb5d318aa0'
x34
=> 30
hex(id(x34))
=> '0x7fdb5d318aa0'
x34=20
hex(id(x34))
=> '0x7fdb5d318960'
why does the address of the variable x34
change when I reassign it value 30
?
Upvotes: 5
Views: 2011
Reputation: 95908
The fundamental misunderstanding you have is that id's belong to Python objects, not the variables. So, any reassignment to a new object, would cause the id's to change:
>>> x = (1,2)
>>> hex(id(x))
'0x107526e48'
>>> x = (2, 4)
>>> hex(id(x))
'0x107526e88'
Note, every time you create a new object, this happens:
>>> x = (1, 2)
>>> hex(id(x))
'0x107526e48'
>>> x = (1, 2)
>>> hex(id(x))
'0x107526d48'
>>> x = (1, 2)
>>> hex(id(x))
'0x107526dc8'
Immutability or lack thereof has nothing to do with it. Note, tuple
objects are immutable. However, there is a CPython implementation detail that small int
s are cached. This is why you'll see the following behavior:
>>> x = 10
>>> hex(id(x))
'0x10714d920'
>>> x = 10
>>> hex(id(x))
'0x10714d920'
>>> x = 10
>>> hex(id(x))
'0x10714d920'
Essentially, in CPython, int
objects between -5 and 256 are singletons. Just like None
:
>>> x = None
>>> id(x)
4413491112
>>> x = None
>>> id(x)
4413491112
However, this wont work the same way with large int
s, and works just like it does with tuple
s:
>>> x = 888
>>> hex(id(x))
'0x107550070'
>>> x = 888
>>> hex(id(x))
'0x10736aef0'
>>> x = 888
>>> hex(id(x))
'0x107550030'
Be careful, though, since id
is only guaranteed unique for the lifetime of the object. So, sometimes, you'll see the same memory being returned from the heap, since the Python interpreter tries to be efficient with memory:
>>> x = 888
>>> hex(id(x))
'0x107550050'
>>> x = 888
>>> hex(id(x))
'0x10736aef0'
>>> x = 888
>>> hex(id(x))
'0x107550090'
>>> x = 888
>>> hex(id(x))
'0x10736aef0'
>>> x = 888
>>> hex(id(x))
'0x107550070'
Again, this might happen with any object:
>>> x = object()
>>> hex(id(x))
'0x1072db120'
>>> x = object()
>>> hex(id(x))
'0x1072db110'
>>> x = object()
>>> hex(id(x))
'0x1072db120'
And the value of the object doesn't matter,
>>> x = 888
>>> hex(id(x))
'0x107549fd0'
>>> x = 999
>>> hex(id(x))
'0x107550090'
>>> x = 777
>>> hex(id(x))
'0x107549fd0'
Indeed, neither does the type necessarily matter either:
>>> class A:
... pass
...
>>> class B:
... pass
...
>>> class C:
... pass
...
>>> for i in range(12):
... if i%3 == 1:
... print(A())
... elif i%3 == 2:
... print(B())
... else:
... print(C())
...
<__main__.C object at 0x107535a58>
<__main__.A object at 0x107535a58>
<__main__.B object at 0x107535a58>
<__main__.C object at 0x107535a58>
<__main__.A object at 0x107535a58>
<__main__.B object at 0x107535a58>
<__main__.C object at 0x107535a58>
<__main__.A object at 0x107535a58>
<__main__.B object at 0x107535a58>
<__main__.C object at 0x107535a58>
<__main__.A object at 0x107535a58>
<__main__.B object at 0x107535a58>
This is all at the discretion of the interpreter implementation.
However, if you keep another reference to an object, the original will not die during reassignment, and that is guaranteed:
>>> hex(id(x))
'0x1072db140'
>>> y = x
>>> hex(id(y)) # guaranteed to be the same as x
'0x1072db140'
>>> x = object()
>>> hex(id(x)) # guaranteed to be new
'0x1072db130'
Upvotes: 8
Reputation:
Basically what you are doing with each assignment is creating a new object of type int
, de-referencing the older one (20 in this case
), and referencing with the variable (x34
) to the new one (30
).
Still be careful, because implementations could be tricky, look this:
>>> x34=20
>>> x34
20
>>> hex(id(x34))
'0x107d67f70'
>>> x34=30
>>> x34
30
>>> hex(id(x34))
'0x107d680b0'
>>> x35=30
>>> hex(id(x35))
'0x107d680b0'
As you can see, two different variables (x34
and x35
) are pointing to the same object ( 30
in this case) when they "theoretically" shouldn't
because the two 30
are different objects even they have the same values.
The Python interpreter is smart enough to realize that 30
is an immutable object, so it avoids wasting memory creating two 30
when with just one is enough because it (the interpreter) will never modify (due to the immutability rules) one object and such modification reflected in the other variable that point to the same object.
Upvotes: 2