Python 3.8 (or CPython 3.8?) added the warning
SyntaxWarning: "is" with a literal. Did you mean "=="?
for the code 0 is 0.
I understand the warning, and I know the difference between is and ==.
However, I also know that CPython caches the object for small integers and shares it in other cases as well.
(Out of curiosity, I just checked the code (header) again.
Small ints are cached in tstate->interp->small_ints.
0 and 1 are even more special and are stored globally in _PyLong_Zero and _PyLong_One.
All new creations of ints are via PyLong_FromLong and that one first checks if it is a small integer and cached.)
Given this background, if you know you have an int object, you could say that the check x is 0 should be safe, right? Also, you could derive that 0 is 0 should always be True, right? Or is this an implementation detail of CPython and other interpreters do not follow this? Which interpreter does not follow this?
Despite this more generic question (which I'm just curious about), consider this more specific (example) code:
def sum1a(*args):
y = 0
for x in args:
if y is 0:
y = x
else:
y = y + x
return y
Vs:
def sum1b(*args):
y = 0
for x in args:
if y == 0:
y = x
else:
y = y + x
return y
Vs:
def sum1c(*args):
y = None
for x in args:
if y is None:
y = x
else:
y = y + x
if y is None:
return 0
return y
Vs:
def sum2(*args):
y = 0
for x in args:
y = y + x
return y
The reason I would sometimes prefer sum1* over sum2 is that depending on the library, sum1* can really be more efficient. E.g. if the argument is a Numpy/TensorFlow/PyTorch array, you really would save a (potentially costly) operation here.
The reason I would prefer sum1a over sum1b is that sum1b would break on certain inputs. E.g. if the input is a Numpy array, this would not work.
Of course, you could use sum1c instead of sum1a. However, sum1a is shorter. So this is nicer?
If the answer to the original question is that this should always work, and if you agree that sum1a is the best option then, how would you get rid of the warning? Is there a simple workaround? In general, I can see that the warning can be useful. So I would not want to disable it completely. I just want to disable it for this specific statement.
Maybe I could wrap it up in a function:
def is_(a, b):
return a is b
And then just use if is_(y, 0): .... Does this work? Is that a good idea?