57

I've always coded in the style of if not value, however, a few guides have brought to my attention that while this style works, it seems to have 2 potential problems:

  1. It's not completely readable; if value is None is surely more understandable.
  2. This can have implications later (and cause subtle bugs), since things like [] and 0 will evaluate to False as well.

I am also starting to apply this idea to other comparisons, such as:

  • if not value vs if value is False
  • if not value vs if value is []

And so goes the list...

The question is, how far do you go with the principle? Where to draw the line, while keeping your code safe?

Should I always use the if value is None style no matter what?

John Doe
  • 3,184
  • 1
  • 15
  • 21
  • 1
    One of Pythons writing disciplines is **duck** typing. In case of `None`, `[]`, `0` and so on that means `If something looks like nothing, acts like nothing then it is nothing.` If you need to be more explicit about value being tested, then use `==`. – nagisa Aug 23 '11 at 01:20

5 Answers5

37

Use a comparison to None if that's what you want. Use "if not value" if you just want to check if the value is considered false (empty list, none, false).

I find "if not value" to be cleaner looking and Pythonic.

Also, be careful with lists. You should not use is when comparing for an empty list. If you know you're getting a list, use if <list> to check if it has any contents (or len()). Try typing this into the interpreter:

>>> a = []
>>> a is []
False

This is because the temporary list you just made has a different address in memory than the one stored at 'a'. You don't see this with None, False, or True because these are all values that are singletons (they all refer to the same section of memory) so using the 'is' keyword works.

You'll also find that CPython interns strings so the following works.

>>> 'a' is 'a'
True

You should not rely on this. It is an implementation detail and this is not specified to work with every version of Python.

Iulian Onofrei
  • 7,489
  • 8
  • 59
  • 96
Jonathan Sternberg
  • 5,796
  • 6
  • 33
  • 57
  • 1
    Good catch. Just learned something new about the `is` operator. :) From a little more research I had found that `if not` is proper for things like `0` and `[]` and `False`, and as said, `if value is None` for `None`. Makes sense, as `if not` will always be boolean, but the `if not` for `None` is a different story, hence `if value is None`. :) – John Doe Aug 22 '11 at 20:46
33

No. If you want to run code when the value is false but isn't None, this would fail horribly.

Use is None if you're checking for identity with the None object. Use not value if you just want the value to be False.

Wooble
  • 80,189
  • 12
  • 97
  • 124
5

Your use of the is operator is a little problematic. if value is [] will always be false, for example, because no two active lists have the same identity. It works great with None because None is a singleton (all references to None are the same object) but for other comparisons, use ==.

However, if value and if not value are perfectly readable and useful. IMHO there's no need to be more specific, unless you need to treat various types of truthy or falsy values differently, as, for example, distinguishing between 0 and None.

kindall
  • 158,047
  • 31
  • 244
  • 289
4

My answer is simple, as it applies to most coding problems: Don't try to write something that just works. Try to express your intent as clearly as possible. If you want to check if a value is false, use if not value. If you want to check for None, write it down. It always depends on the situation and your judgement.

You should not try to find rules which can be applied without thinking. If you find those rules, it's a job for a computer, not for a human! ;-)

Tom Dufall
  • 477
  • 3
  • 12
Achim
  • 14,333
  • 13
  • 70
  • 128
1
if not value:
    pass

is fine and "pythonic". It does not cause subtle bugs, the rules are explicit and (I find) easy to understand.

If you need to differentiate between False and None, as you mentioned use:

if not value is None:  # or False, or == [], etc.
    pass

# more readable
if value is not None:  # or False, or != [], etc.
    pass

I find the above rarely necessary though.

In general, it is preferred to make positive conditions, and put them first. They are easier to understand at a glance and hold up well as complexity increases (as it always seems to).

if value:
    pass
else:
    pass
Gringo Suave
  • 25,443
  • 6
  • 77
  • 69
  • That's why I had said it _can_ cause subtle bugs. I'd rather not go into details, but this [post](http://boodebr.org/main/python/tourist/none-empty-nothing) should explain it. :) – John Doe Aug 22 '11 at 20:54
  • 1
    Apologies, but you need to determine the correct test and apply it. The linked blog post is by someone who doesn't understand python's truth test rules and wants to use C's instead. "Subtle" bugs are what happen when one doesn't understand the rules. – Gringo Suave Aug 22 '11 at 22:05
  • `value is not None` tends to read better than `not value is None`, and both generate the exact same code (namely, the `is not` operator). – chepner Mar 01 '19 at 13:57
  • Yes I agree. Would still avoid it however. – Gringo Suave Mar 02 '19 at 17:24