3

I just started with Python and my online professor recommended using is and is not only when comparing a value to True, False, or None (or at least that is how I understood what he was saying.)

Now in my head, I equate is with the JavaScript === and is not with the JavaScript "!==", and I think it is accepted as best practice to use === and !== as often as you can to avoid forced type conversion.

First of all, is it true that we don't want to use is and is not as much as === and !== in JavaScript, and if so, why not?

Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
Ryan Scharfer
  • 505
  • 1
  • 3
  • 11
  • 9
    `is`/`is not` is not at all comparable to Javascript's `===`/`!==`. – interjay Nov 06 '14 at 11:44
  • See [this](http://stackoverflow.com/a/2988117/2206044). – Azar Nov 06 '14 at 11:45
  • Technically, `is` and `is not` are the same as `===` and `!==` in JavaScript. `===` and `!==` in JavaScript check identity equality on objects. It just happens that it works that way for numbers and strings in Python too because numbers and strings in Python are objects, unlike in JavaScript where they aren't. –  Nov 06 '14 at 12:08

3 Answers3

2

Python's is and == operators do two different things. You also can't compare is with JS's ===.

Simply, == tests if two identifiers are equal, while is tests whether two identifiers have the same memory address, therefore whether "they are each other"; the way they behave is just like it sounds:

#0 equals None, so returns True
0 == None

#But it isn't None, hence returns False
0 is None

#However, 0 is 0, so returns True
0 is 0
  • Consider adding some examples in Javascript to illustrate how `===` and `is` operators "cannot be compared" as you state. All answers given so far are arguably incomplete because they only explain the Python side of the question without saying how exactly JS and Python differ in this context. – Seldom 'Where's Monica' Needy Oct 16 '15 at 19:23
1

Noneis a singleton, so you can compare object identity (is/is not) instead of equality (==/!=) - whenever you access None, you are getting the same object.

For almost all other cases, you should use equality (see e.g. Why does comparing strings in Python using either '==' or 'is' sometimes produce a different result?). In terms of "avoid[ing] forced type conversion" - Python is strongly typed and will never implicitly convert. Also, you can't really "cast" a type in Python - converting e.g. an int to str creates a new, separate object.

This is particularly important as None is often used to mark no return - if False or 0 or [] or anything else that evaluates False-y is a valid return, evaluating "truthiness" will give misleading results.

def yes_or_no(s):
    """Convert 'yes' or 'no' to boolean, or implicitly return None."""
    if s.lower() == "yes":
        return True
    elif s.lower() == "no":
        return False

result = some_func("foo")

if result: # wrong, covers None and False
    ...

if result is not None: # right, covers None only
    ...

Per the style guide:

Comparisons to singletons like None should always be done with is or is not, never the equality operators.

Also, beware of writing if x when you really mean if x is not None -- e.g. when testing whether a variable or argument that defaults to None was set to some other value. The other value might have a type (such as a container) that could be false in a boolean context!


Note that you generally don't compare True or False. Again, from the style guide:

Don't compare boolean values to True or False using ==.

Yes:   if greeting:
No:    if greeting == True:
Worse: if greeting is True:

See also: Use of True, False, and None as return values in python functions

Community
  • 1
  • 1
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • 1
    `checking equality will give misleading results`. Are you sure about that? Is your example (`if result`) testing equality (vs *truthfulness*)? Otherwise, nice overview – loopbackbee Nov 06 '14 at 11:55
  • I think `some_func` should be `yes_or_no` – Elisha Nov 06 '14 at 11:57
0

We shouldn't use is and is not for comparing values other than True, False and None, probably because of the following weird results:

>>> 20 is 19+1
True
>>> 19+1 is 20
True
>>> 1999+1 is 2000
False
>>> -0 is 0
True
>>> -0.0 is 0.0
False
>>> -0.0 is not 0.0
True
>>> 1999+1 is not 2000
True
>>> -0.0 == 0.0
True
>>> 1999+1 == 2000
True
>>> 1999+1 != 2000
False
>>> -0.0 != 0.0
False 
Irshad Bhat
  • 8,479
  • 1
  • 26
  • 36