3

From what I've seen, the only time None and False behave differently is when they're compared to each other (for equality). Am I missing something, or is it ok to use only one or the other as long as you're consistent in your usage? Is there any reason to use one over the other?

Alec
  • 8,529
  • 8
  • 37
  • 63
  • 3
    One obvious difference is that they mean different things. Use `None` when you want to say "nothing", much like `null` or `nil` might be used in other languages. Use `False` when you want to say "not true". The one you use can make your code more readable, or more confusing. – ChrisGPT was on strike Mar 23 '19 at 11:47
  • ,Doesn't "nothing" resolve to false, though? If a list contains nothing, it's `False` as a boolean but `None` as a concept – Alec Mar 23 '19 at 11:49
  • When you have an optional boolean flag. In that case `None` would indicate the flag was not set. – taras Mar 23 '19 at 11:51
  • In Boolean context, `None` is falsy. But that doesn't mean it's _false_. Again, it's in the semantics. What are you trying to tell the programmer? `1` (along with most other things) is truthy. Would you return `1` from a function to indicate a `True` Boolean result? What about `1.5`, which is also truthy? Or the string `"false"` (also truthy). – ChrisGPT was on strike Mar 23 '19 at 11:51

3 Answers3

7

I would emphasize here the semantical difference rather than the behavioral.

Let's consider a couple of functions:

def find_user(criteria):
    if is_met(criteria):
        return User(...)
    return None

# ...vs 

def has_email(user):
    return bool(user.email)

To me, in the above example, None means an absence of the value, while False means the boolean falsity.

An analogy here could be an emergence of the bool type in C++. Historically, C (ab)used int for boolean logic, but C++ introduced a dedicated bool type which makes intentions behind some variables/function signatures clearer.

Ivan Velichko
  • 6,348
  • 6
  • 44
  • 90
1

They are different types. Although, in practice, they behave quite similarly. You could also replace False with: "", [], (,) or 0 and everything will mostly work. Python automatically converts your variable into a boolean whenever you pass it to if, while, to any boolean operators (eg. or, and, etc) or any builtin function expecting a boolean (side note: although or, and and do convert your value to boolean while deciding what to return, the end result will be your unconverted value). That's why it's difficult to tell the difference.

However, most developers will consider None to be similar to a null value in other languages, which is an error or unitialized value. Whilist False will usually be considered an expected and fully initialized value. Therefore, it will be easier for most people to read your code if you stick to that convention.

Further elaborating that point, let's consider the C Python implementation. A typical if statement will be converted to the POP_JUMP_IF_FALSE (or POP_JUMP_IF_TRUE) instruction. This is how that is implemented:

TARGET(POP_JUMP_IF_FALSE) {
    PyObject *cond = POP();
    int err;
    if (cond == Py_True) {
        Py_DECREF(cond);
        FAST_DISPATCH();
    }
    if (cond == Py_False) {
        Py_DECREF(cond);
        JUMPTO(oparg);
        FAST_DISPATCH();
    }
    err = PyObject_IsTrue(cond);
    Py_DECREF(cond);
    if (err > 0)
        ;
    else if (err == 0)
        JUMPTO(oparg);
    else
        goto error;
    DISPATCH();
}

As you can see, if the value passed to if is a boolean the interpreter will know what to do right away. Otherwise, it will call PyObject_IsTrue, which will try to convert the object to a bool using any means possible (__bool__, __nonzero__, __len__, and even comparing to None explicitly).

Rafael Almeida
  • 2,377
  • 3
  • 22
  • 32
0

If you are checking if a value is assigned or exists, you can use None.

dct = {'key':'value'}
x = dct.get('key', None) # Get the value or get`None if it doesn't exist

def func(...):
   if condition:
      return Object()
   return None

Whereas if you know the value will exist but want to check it's property, use False

if empty_list: #An empty list evaluates to `False`
   do something
if not bool_var:
   do something

Also bool(None) evaluates to False

Alec
  • 8,529
  • 8
  • 37
  • 63
Devesh Kumar Singh
  • 20,259
  • 5
  • 21
  • 40
  • 3
    Here, `empty_list is False` _won't_ be true. The `empty_list` isn't the same object as `False`. `is False` is different from "regular" truthiness tests. It's [an object identity comparator](https://stackoverflow.com/q/22885931/354577). – ChrisGPT was on strike Mar 23 '19 at 11:59
  • 2
    I think `if not` is more idiomatic than `if ... is False`, and `.get` returns `None` by default if you don't specify a default argument. Also, as @Chris noted, `is` tests reference equality. – gmds Mar 23 '19 at 11:59
  • Edited accordingly. Thanks for the suggestions – Devesh Kumar Singh Mar 23 '19 at 12:01
  • If the edits looks good! Please consider upvoting @Chris gmds :) – Devesh Kumar Singh May 09 '19 at 17:59