Python does not have primitive types. Everything in Python is an object.
Generally, the only place you should use is
are on language-guaranteed singletons, like True
, False
, and None
or, say for debugging purposes, you actually want to check object identity.
In every other case, you will be relying on implementation details and implementation-specific optimizations if you use is
to mean equality (e.g. the peep-hole optimizer and string interning). The equality operator is ==
and should be used in those cases. While often, the Python interpreter will optimize immutable types, you should still not rely on identity when you mean equality, because mostly that is not a language guarantee.
As an example, while on CPython 3.7, you can "safely" be tempted choose to use is
to compare small integers because they are cached, this is an implementation detail that should not be relied upon. This is free to change in Python 3.9 or whenever. Also, see the comment by @user2357112 about how it isn't even necessarily safe for the small integers that are cached! To reiterate: it is not a language guarantee - it is a side-effect of how it was implemented.
And also, again, it only applies to small integers, [-5, 256] so:
>>> def add(a, b): return a + b
...
>>> 16 is add(8, 8)
True
>>> 1000 is add(500, 500)
False
Note, I put the actual addition in a function, the interpreter frequently optimizes immutable literals and arithmetic expressions:
>>> 1000 is (500 + 500)
True
But it should be obvious now why you cannot rely on that.
Another example where it is appropriate to use is
for "equalityish" comparisons is to compare enum
types, which are guaranteed singletons:
import enum
class Color(enum.Enum):
RED = 1
BLUE = 2
RED = Color.RED
BLUE = Color.BLUE
print(Color(1) is RED)