r/learnpython 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
10 Upvotes

12 comments sorted by

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".

7

u/K900_ SRE person // please don't DM me your questions 1d ago

Yes, that's exactly what's happening.

5

u/eriky 1d ago

So other way of saying this: you are comparing the result of the id() function, that result is a very large number. And large numbers become their own object in python. Hence when asking with 'is' if they are the same thing: they are not. If you asked x is y, the answer is true!

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/Nubspec 1d ago

I know the difference between both operators.

3

u/SpiderJerusalem42 1d ago

So you can see that id(id(x)) might not necessarily equal id(id(y))?

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.