Alec
Alec

Reputation: 9536

When should I use None vs False?

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?

Upvotes: 3

Views: 1163

Answers (3)

Ivan Velichko
Ivan Velichko

Reputation: 6709

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.

Upvotes: 7

Rafael Almeida
Rafael Almeida

Reputation: 2397

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).

Upvotes: 1

Devesh Kumar Singh
Devesh Kumar Singh

Reputation: 20490

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

Upvotes: 0

Related Questions