Difference between 'is' and '=='

Felipe Almeida Lessa felipe.lessa at gmail.com
Tue Mar 28 10:03:22 CEST 2006

Em Seg, 2006-03-27 às 23:02 -0800, alex23 escreveu:
> Felipe Almeida Lessa wrote:
> > I said [constants defined in your code] can (maybe "should"?) be used with "is", and
> > AFAICT I'm right as well:
> > >>> b = a
> > >>> b is a
> > True
> You should _never_ use 'is' to check for equivalence of value. Yes, due
> to the implementation of CPython the behaviour you quote above does
> occur, but it doesn't mean quite what you seem to think it does.

/me not checking for value. I'm checking for identity. Suppose "a" is a
constant. I want to check if "b" is the same constant.

> Try this:
> >>> UPPERLIMIT = 100
> >>> i = 0
> >>> while not (i is UPPERLIMIT):
> >>>     i+=1
> >>>     print i
> Comparing a changing variable to a pre-defined constant seems a lot
> more general a use case than sequential binding & comparison...and as
> this should show, 'is' does _not_ catch these cases.

That's *another* kind of constant. I gave you the example of
socket.AF_UNIX, the kind of constant I'm talking about. Are you going to
sequentially create numbers until you find it? Of couse not.

The problem with Python (and other languages like Jave) is that we don't
have a type like an enum (yet) so we have to define constants in our
code. By doing an "is" instead of a "==" you *can* catch some errors.
For example, a very dummy function (picked MSG_EOR as its value is
greater than 99):

from socket import MSG_EOR, MSG_WAITALL

def test(type):
	if type is MSG_EOR:
		print "This *is* MSG_EOR"
	elif type == MSG_EOR:
		print "This maybe be MSG_EOR"
		print "*Not MSG_EOR"

Now testing it:

>>> test(MSG_EOR)
This *is* MSG_EOR

Fine, but:

>>> print MSG_EOR
>>> test(128)
This maybe be MSG_EOR

This is a mistake. Here I knew 128 == MSG_EOR, but what if that was a
coincidence of some other function I created? I would *never* catch that
bug as the function that tests for MSG_EOR expects any integer. By
testing with "is" you test for *that* integer, the one defined on your
module and that shouldn't go out of it anyway.

Of course using an enum should make all said here obsolete.


More information about the Python-list mailing list