Why do python variables of same value point to the same memory address?
Question:
I ran into an interesting case today wherein
a = 10
b = 10
print (a is b)
logged out True
. I did some searching and came across the concept of interning. Now that explains why True
is correct for the range [-5, 256]. However, I get the same results even while using floats. Please help me understand why.
Here is the part I don’t get-
a = 1000.00
b = 999.99 + 0.01
print (a is b)
# Output was 'True'
I expect the output to be False
since a
‘s value is assigned before running the program, whereas b
‘s value is determined at run-time as a result of expression evaluation and hence should have a different memory address.
I’d also appreciate it if you could point out a case where a==b
is True
, but a is b
evaluates to False
where both a
and b
are of type float
Answers:
What you are looking at in your case is called "constant folding". That’s an implementation detail, not a language specification – meaning there is no guarantee that this behaviour will remain the same and you should not rely on it in your code. But, in general it comes down to the fact that things that can be calculated "statically" are optimised away to their simplest form before the code is actually being run.
Take a look at the output of the following snippet
import dis
def f():
return 0.1 + 0.9
def g():
a = 0.1
b = 0.9
return a+b
dis.dis(f)
dis.dis(g)
You will notice that there is no addition performed in f
, even though looking at the code addition is clearly there.
As for two same-valued variables having different memory addresses, its not very difficult – any calculations that cannot be optimised away pre-runtime will yield you variables at different memory addresses if they are not within interning range.
a = 1
b = 1
for _ in range(1000):
a += 1
b += 1
print(f"{id(a) = }")
print(f"{id(b) = }")
print(f"{a == b = }")
print(f"{a is b = }")
I ran into an interesting case today wherein
a = 10
b = 10
print (a is b)
logged out True
. I did some searching and came across the concept of interning. Now that explains why True
is correct for the range [-5, 256]. However, I get the same results even while using floats. Please help me understand why.
Here is the part I don’t get-
a = 1000.00
b = 999.99 + 0.01
print (a is b)
# Output was 'True'
I expect the output to be False
since a
‘s value is assigned before running the program, whereas b
‘s value is determined at run-time as a result of expression evaluation and hence should have a different memory address.
I’d also appreciate it if you could point out a case where a==b
is True
, but a is b
evaluates to False
where both a
and b
are of type float
What you are looking at in your case is called "constant folding". That’s an implementation detail, not a language specification – meaning there is no guarantee that this behaviour will remain the same and you should not rely on it in your code. But, in general it comes down to the fact that things that can be calculated "statically" are optimised away to their simplest form before the code is actually being run.
Take a look at the output of the following snippet
import dis
def f():
return 0.1 + 0.9
def g():
a = 0.1
b = 0.9
return a+b
dis.dis(f)
dis.dis(g)
You will notice that there is no addition performed in f
, even though looking at the code addition is clearly there.
As for two same-valued variables having different memory addresses, its not very difficult – any calculations that cannot be optimised away pre-runtime will yield you variables at different memory addresses if they are not within interning range.
a = 1
b = 1
for _ in range(1000):
a += 1
b += 1
print(f"{id(a) = }")
print(f"{id(b) = }")
print(f"{a == b = }")
print(f"{a is b = }")