Let’s go through your results one by one and see what’s going on:
>>> ed_user is our_user
True
So this is the situation. We have two variables, that reference the same object. Nothing special about that. You can even replicate that by just doing ed_user = our_user = 'something'
.
>>> id(ed_user) == id(our_user)
True
Since both variables are identical, the return value of id()
matches for both variables. Obviously then the difference is also zero.
>>> id(ed_user) is id(our_user)
False
Now this is where it get’s interesting. We know the return values match, but according to this check, the return values are not the same objects. id()
returns an integer, so apparently those two integers are not identical. How is that possible? Well, it’s rather simple: Python only reserves fixed ids for a small set of small numbers. For all larger numbers, new integer objects (actual objects!) are created as they are needed. So in your case, the number is 139859764807552
. That’s certainly a large number, so Python will create an integer object for the id(ed_user)
call, … and for the id(our_user)
call. So we have two different integer objects for this. And two different objects of course are never identical. So far so good.
>>> id(id(ed_user)) == id(id(our_user))
True
Now here it gets crazy. Above, we had two calls of id()
that returned integer objects that both lived at the same time (since that was necessary for the comparison). Now, id()
guarantees us to never return the same integer for two distinct objects that exist at the same time. This was the case in the previous call, and that’s why we ended up having two different integer objects (with the same value).
But here, everything works a bit differently: We are calling id(ed_user)
first, this gives us an int object (let’s call it a
) for the value 139859764807552
. We then call id()
on it and get an int object for the id of a
; let’s call that id_a
. At this point, a
is no longer referenced, and also not needed for the comparisong (we are comparing id_a
after all). So Python discards it. Next, we are calling id(out_user)
. This gives us an int object (b
), also for the value 139859764807552
. Since a
is no longer around, b
can go at the place of a
, ending up with the same id. So we call id()
on b
and get back an integer object id_b
. Since b
is at the same memory position as a
was, and since ids are based on memory position, id_a
equals to id_b
(and again id_a is id_b
is not the case).