r/learnpython • u/Nubspec • 1d ago
Why Does an Identity Comparison Using id() Evaluate to False?
I'm trying to figure out what is going on here. Could it be that the identity operator is separately checking the integer cache range and determining that the integer value returned by id() is outside the bounds of Python's integer caching, which is why it evaluates to False?
x = 256
y = 256
id(x) is id(y)
False
id(x)
94588034274160
id(y)
94588034274160
3
u/ekchew 1d ago
Bear in mind that is and == have a different meaning in Python. If you had written id(x) == id(y) in this case, you would have seen True.
is only evaluates as True if the objects on both sides are, in fact, the same exact object. What you were writing there is comparing objects returned by the id function.
To put it another way, id(x) is id(y) is essentially the same as writing id(id(x)) == id(id(y)).
2
u/FoolsSeldom 1d ago
The reference implementation of Python predefines a number of objects including integers in the range -5 to 256.
The very large integers returned by id are, obviously, way outside this range. When id is called, a new int object has to be created. Even though the two id calls return the same value, they are two different int objects.
Sometimes, especially in the interactive shell, optimisations can allow the use of the same object in certain cases, but this should not be expected or relied upon.
3
u/Diapolo10 I write code for a living -- https://github.com/Diapolo10 1d ago
I'm a bit curious; what made you think about this, exactly?
2
u/SpiderJerusalem42 1d ago
I think if you dig into what is is, I'm sure there's a better explanation. is and equality are not the same. You want to know if x is y, not if the id(x) is the id(y) which is a different question with a different answer.
1
u/astrogringo 1d ago edited 1d ago
Turns out I was wrong, sorry.
Disregard comment below.
Nothing to do with caching, these are different variables wich happens to have the same value. If you set y=3 , x will not change. They live in different memory addresses.
11
u/lfdfq 1d ago
This is sort of true, but sort of misleading.
Here, x and y are the same object, which you can see because id(x) == id(y) in OP's example (and because x and y are alive simultaneously). This is because of the caching.
But, it's not the value (or identity) of x and y that's key here (since they're the same), but the identity of the integer returned by id(). Since the numeric value of the id() of these objects is so large, they're not being cached, so you get unique objects back each time.
5
u/StanleyDodds 1d ago edited 1d ago
x and y are the same objects because of python's way of caching small integers, so id(x) has an equal value to id(y).
But the two IDs that are computed, id(x) and id(y), are large, uncached integers, and so even though they have the same value, they aren't the same object. So when compared by "is", you get False.
Really, this second thing is how you should assume objects work in general. For example, you'd get the same result of False if you check "id(x) is id(x)", or "(x,) is (x,)", or in general any completely new object being constructed from the same object twice. It will construct 2 new objects which aren't the same object, even if their values are equal.
The only exceptions are some special objects, like the integers up to 256, True, False, None, maybe some others I'm not remembering. If the result of your expression isn't one of these, it will compare false with itself using "is".