How to check if a list is empty in Python

There is one idiomatic way to do this, it is also the fastest, and it catches rather more than an empty list — which is fine until the day it is not.

The answer

if not items:
    ...
if not empty : True
if not full  : False

PEP 8 is explicit about this: “For sequences, use the fact that empty sequences are false.”

It is also the fastest

Two million iterations each:

not x       : 0.0154 s
len(x) == 0 : 0.0293 s
x == []     : 0.0509 s

not x calls the object’s truth test, which for a list is a length check straight off the object header. len(x) == 0 does the same work and then builds an integer and compares it. x == [] builds a whole new empty list first and then runs a full sequence comparison.

None of this matters in a loop that runs ten times. It is nice that the readable version is also the cheap one.

What else it catches

Here is the catch, and it is worth knowing before you rely on the idiom:

not []    -> True      not ''    -> True
not ()    -> True      not 0     -> True
not {}    -> True      not 0.0   -> True
not set() -> True      not None  -> True
                       not False -> True

not x is true for an empty list, an empty string, zero, and None. So this function cannot tell the difference between “you gave me an empty list” and “you gave me nothing at all”:

def process(items=None):
    if not items:
        return "nothing to do"
process([])   : nothing to do
process(None) : nothing to do

Usually that is exactly what you want — both mean “no work”. Occasionally it is not, and then you have to say so:

def process_strict(items):
    if items is None:
        return "no list was given"
    if not items:
        return "an empty list was given"
strict, []   : an empty list was given
strict, None : no list was given

The rule I use: if None and empty mean the same thing to the caller, use not items. If the distinction is meaningful — “field absent” versus “field present but empty”, which is common with JSON — check for None explicitly.

It does not work on generators

This one is a genuine trap, because there is no error:

bool(a generator)        : True
bool(an empty generator) : True
list(empty_gen())        : []

A generator is always truthy. It has no length, and it cannot know whether it will produce anything without running — which would consume the value it produced.

So if not gen: is always false, whatever the generator does. To find out whether there is anything in it you have to ask for an item:

sentinel = object()
if next(gen, sentinel) is sentinel:
    ...   # it was empty
next(empty_gen(), sentinel) is sentinel : True

Note that this consumes the first item, so you need to use the value you just pulled rather than iterating from the start.

The same applies to anything lazy — a file object, a map, a zip, a database cursor. If you need to test for emptiness, either materialise it with list() or restructure so you do not need to.

Custom classes get it for free

class Basket:
    def __len__(self):
        return len(self.items)
bool(Basket([]))  : False
bool(Basket([1])) : True

Defining __len__ is enough — Python falls back to it when there is no __bool__. If you define both, __bool__ wins, which is worth knowing if you ever want a container that is truthy while empty.

A note on numpy and pandas

If items might be a numpy array or a pandas Series, if not items: raises:

ValueError: The truth value of an array with more than one element is ambiguous.
Use a.any() or a.all()

They refuse to guess whether you meant “any element is true” or “the container is non-empty”. Use .size == 0 for numpy, or .empty for a pandas DataFrame or Series. The article on iterating DataFrames covers the same error from the other direction.

About Netcup (advertisement)

The German host Netcup offers, among other things, affordable and powerful web hosting packages, KVM-based root servers and dedicated servers. With our voucher codes you can save even more (6€ off your first order, 30% off all KVM-based root servers, ...).