If you use is
only to compare to None
, which I believe you should, then the question is irrelevant as None
has a well-defined address
>>> id(None)
10306432
>>> id(None)
10306432
>>> a = None
>>> id(a)
10306432
I have yet to encounter a situation where a is b
yields a result different from id(a) == id(b)
, but you still don't want to use is
carelessly :
>>> a = 1
>>> b = 1
>>> id(a), id(b), id(1)
(10914496, 10914496, 10914496)
# 1 has a single address, is fails to recognize that a and b were created separately.
>>> a = 500
>>> b = 500
>>> id(a), id(b), id(500)
(140251806972464, 140251806973200, 140251806973744)
# Unlike the previous case, 500 is created multiple times, each with a different address
>>> a, b = 500, 500
>>> id(a), id(b), id(500)
(140251806972336, 140251806972336, 140251806972464)
# Several instances during the same initialization are created with a single address
>>> a, b = 500, 5*100
>>> id(a), id(b), id(500)
(140251806973104, 140251806973200, 140251806971280)
# However it only works if all are created in the same manner...
>>> a, b = 5*100, 5*100
>>> id(a), id(b), id(500)
(140251806971920, 140251806973392, 140251806973104)
# ... and they have to be created explicitely.
>>> a = 500 ; b = 500
>>> id(a), id(b), id(500)
(140251806973104, 140251806973104, 140251806972464)
# Separating with a semicolon does not change this fact...
>>> 500 is 500
True
>>> a is b
True
>>> a = 500
>>> a is 500
False
>>> a = 500 ; a is 500
True
# However being in the same line is not a basis for always having the same address, even if all values were created explicitly :
>>> any([a is 500 for a in [500]])
False
Other objects each have their own erratic behavior :
>>> a = 'hello'
>>> b = 'hello'
>>> id(a), id(b), id('hello')
(140251789045408, 140251789045408, 140251789045408)
>>> a = 'hello' + ' '
>>> b = 'hello' + ' '
>>> id(a), id(b), id('hello' + ' ')
(140251789044344, 140251789012472, 140251789012920)
>>> a = []
>>> b = []
>>> id(a), id(b), id([])
(140251789066632, 140251789069704, 140251789174216)
I would conclude that the behaviors of is
and id
are too unreliable for (a is b) == (id(a) == id(b))
to be useful even if it were true, at least in the case of immutable objects.
I personally would never think of using is
in any case other than
if x is None:
pass
and I reserve id
for only mutable objects or custom classes.