When to use == and when to use is?
Question:
Curiously:
>>> a = 123
>>> b = 123
>>> a is b
True
>>> a = 123.
>>> b = 123.
>>> a is b
False
Seems a is b
being more or less defined as id(a) == id(b)
. It is easy to make bugs this way:
basename, ext = os.path.splitext(fname)
if ext is '.mp3':
# do something
else:
# do something else
Some fnames unexpectedly ended up in the else block. The fix is simple, we should use ext == '.mp3'
instead, but nonetheless if ext is '.mp3'
on the surface seems like a nice pythonic way to write this and it’s more readable than the “correct” way.
Since strings are immutable, what are the technical details of why it’s wrong? When is an identity check better, and when is an equality check better?
Answers:
As far as I can tell, is
checks for object identity equivalence. As there’s no compulsory “string interning”, two strings that just happen to have the same characters in sequence are, typically, not the same string object.
When you extract a substring from a string (or, really, any subsequence from a sequence), you will end up with two different objects, containing the same value(s).
So, use is
when and only when you are comparing object identities. Use ==
when comparing values.
They are fundamentally different.
==
compares by calling the __eq__
method
is
returns true if and only if the two references are to the same object
So in comparision with say Java:
is
is the same as ==
for objects
==
is the same as equals
for objects
Simple rule for determining if to use is or == in Python
Here is an easy rule (unless you want to go to theory in Python interpreter or building frameworks doing funny things with Python objects):
Use is only for None
comparison.
if foo is None
Otherwise use ==.
if x == 3
Then you are on the safe side. The rationale for this is already explained int the above comments. Don’t use is if you are not 100% sure why to do it.
It would be also useful to define a class like this to be used as the default value for constants used in your API. In this case, it would be more correct to use is than the == operator.
class Sentinel(object):
"""A constant object that does not change even when copied."""
def __deepcopy__(self, memo):
# Always return the same object because this is essentially a constant.
return self
def __copy__(self):
# called via copy.copy(x)
return self
You should be warned by PyCharm when you use is
with a literal with a warning such as SyntaxWarning: "is" with a literal. Did you mean "=="?
. So, when comparing with a literal, always use ==
. Otherwise, you may prefer using is
in order to compare objects through their references.
Curiously:
>>> a = 123
>>> b = 123
>>> a is b
True
>>> a = 123.
>>> b = 123.
>>> a is b
False
Seems a is b
being more or less defined as id(a) == id(b)
. It is easy to make bugs this way:
basename, ext = os.path.splitext(fname)
if ext is '.mp3':
# do something
else:
# do something else
Some fnames unexpectedly ended up in the else block. The fix is simple, we should use ext == '.mp3'
instead, but nonetheless if ext is '.mp3'
on the surface seems like a nice pythonic way to write this and it’s more readable than the “correct” way.
Since strings are immutable, what are the technical details of why it’s wrong? When is an identity check better, and when is an equality check better?
As far as I can tell, is
checks for object identity equivalence. As there’s no compulsory “string interning”, two strings that just happen to have the same characters in sequence are, typically, not the same string object.
When you extract a substring from a string (or, really, any subsequence from a sequence), you will end up with two different objects, containing the same value(s).
So, use is
when and only when you are comparing object identities. Use ==
when comparing values.
They are fundamentally different.
==
compares by calling the__eq__
methodis
returns true if and only if the two references are to the same object
So in comparision with say Java:
is
is the same as==
for objects==
is the same asequals
for objects
Simple rule for determining if to use is or == in Python
Here is an easy rule (unless you want to go to theory in Python interpreter or building frameworks doing funny things with Python objects):
Use is only for None
comparison.
if foo is None
Otherwise use ==.
if x == 3
Then you are on the safe side. The rationale for this is already explained int the above comments. Don’t use is if you are not 100% sure why to do it.
It would be also useful to define a class like this to be used as the default value for constants used in your API. In this case, it would be more correct to use is than the == operator.
class Sentinel(object):
"""A constant object that does not change even when copied."""
def __deepcopy__(self, memo):
# Always return the same object because this is essentially a constant.
return self
def __copy__(self):
# called via copy.copy(x)
return self
You should be warned by PyCharm when you use is
with a literal with a warning such as SyntaxWarning: "is" with a literal. Did you mean "=="?
. So, when comparing with a literal, always use ==
. Otherwise, you may prefer using is
in order to compare objects through their references.