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