Edit: Even the results in REPL are not always reproducibly. Don't use the
is
operator for
str
,
bytes
,
int
,
float
.
I guess the AST-Parser and/or Bytecode optimizer scans for equal literals and replaces them with a reference to the same object.
This explains why the first result is
True
and the second one
False
.
In interactive mode (repl) a and b referring to two different
str
objects.
Use only the
is
operator, if you want to check Identity.
You can check the identity of Singletons like
None
,
True
,
False
,
...
.
Also of all other objects like
list
,
tuple
,
dict
,
set
, functions, classes, types.
Surprise, also for
str
and
bytes
, but not if you create new literals.
WORK = "work"
RUN = "run"
STOP = "stop"
def some_function(choice):
if choice is WORK:
print('Go to work')
elif choice is RUN:
print('You are late. Run baby..')
elif choice is STOP:
print('Go Home.')
else:
print('Got invalid input')
some_function("work") # <- invalid input
some_function(WORK)
"work" is not WORK and "run" is not RUN and "stop" is not STOP
The good thing is, if you enter this in Python 3.8, you get a nice SyntaxWarning and there is some auto correction going on in the background.
Error:
SyntaxWarning: "is not" with a literal. Did you mean "!="?
With mutable objects this should be clear.
d1 = {}
d2 = {}
The name d1 refers to a dict
The name d2 refers to another new dict
Same for
tuple
-
list
-literals.
Now a example with immutable objects:
a = 5
b = 5
Name a and name b should refer to two different objects.
But this it not the case. The Python interpreter creates a range of numbers in memory and literals like the
5
is reusing the object for
5
from memory. But this is not the case for bigger numbers. You know, memory is limited.
The differences you see, comes from optimization and implementation details.
If you want to check for equality, don't use the
is
operator.