Python Basic Doubt
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Sun Aug 11 04:03:04 EDT 2013
On Sat, 10 Aug 2013 17:42:21 -0700, Gary Herron wrote:
> But for each of your examples, using "==" is equivalent to using "is".
> Each of
> if something == None
> if device == _not passed
> if device != None
> would all work as expected. In none of those cases is "is" actually
> needed.
py> class Weird:
... def __eq__(self, other):
... return True
...
py> definitely_not_None = Weird()
py> definitely_not_None == None
True
Oops.
Now Weird is, naturally, weird. But classes may have a legitimate reason
to claim to be equal to None, or at least the creator of the class may
believe he has a legitimate reason. It's not forbidden, therefore you
have to assume somebody will do so.
But more importantly, in checking whether some value is a sentinel, the
*intention* of the code is to check that the value *actually is* the
sentinel, not merely that it happens to be equal to the sentinel. To give
an analogy: when you hand the codes to the nuclear arsenal to the
President, you want to make sure that it actually *is* the President, not
some impostor who merely looks and sounds like him.
"value == None" not only risks doing the wrong thing if passed some weird
object, but it fails to match the intention of the code. Whereas "value
is None" is idiot-proof (it cannot fail -- short of hacking the compiler,
you cannot change the meaning of either "is" or "None"), it matches the
intention of the code, and therefore is clearer, more explicit, and more
idiomatic. And as a bonus, it's faster too. But speed is not why you
should use it. You should use it because it matches the intention of the
code. You don't want to test for some arbitrary person who happens to
look like the President, you want to test for the President himself, and
nobody but the President.
On the other hand, code like "x is 42.9" does not match the intention of
the code, and is likely to fail. "is" is not a synonym for "==".
Conflating them is a bad thing, whether you use "is" to check for
equality or "==" to check for identity.
> Given that, and the implementation dependent oddities, I still believe
> that it is *highly* misleading to teach a beginner about "is".
Careful -- it's not "is" which is implementation-dependent. The "is"
operator works the same way in every Python implementation. What differs
are the rules for when new instances are created from literals.
> Here's a challenge: What is the simplest non-contrived example where an
> "is" comparison is *required*. Where substitution of an "==" comparison
> would cause the program to fail or be significantly less efficient? (I'm
> not including the nearly immeasurably small timing difference between
> v==None and v is None.)
Easy-peasey. Test code often relies on "is" to check object identity.
Occasionally such comparisons work there way into production code, but
they're common in tests.
In one of my test suites, I have code that verifies that a certain
function which takes a list as argument does not modify it in place. So
my unit test looks like this:
def testNoInPlaceModifications(self):
# Test that the function does not modify its input data.
data = self.prepare_data()
assert len(data) != 1 # Necessary to avoid infinite loop.
assert data != sorted(data)
saved = data[:]
assert data is not saved # <<<=== LOOK HERE ===
_ = self.func(data)
self.assertListEqual(data, saved, "data has been modified")
Note that is would be *wrong* to replace the "is not" comparison with not
equal to. The list and its copy are, in fact, equal. If they aren't
equal, the test fails.
In this case, the assertions are there as verifiable comments. They
communicate to the reader, "These are the assumptions this test relies
on", except unlike comments, if the assumptions are violated, the test
will fail. Unlike comments, they cannot ever get out of date.
--
Steven
More information about the Python-list
mailing list