Python: Wie prüft man ob eine Liste leer ist?

Es gibt genau eine übliche Schreibweise dafür, sie ist zugleich die schnellste, und sie erfasst einiges mehr als eine leere Liste — was in Ordnung ist, bis zu dem Tag an dem es das nicht mehr ist.

Die Antwort

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

PEP 8 ist dazu deutlich: “For sequences, use the fact that empty sequences are false.”

Sie ist auch die schnellste

Je zwei Millionen Durchläufe:

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

not x ruft den Wahrheitstest des Objekts auf, was bei einer Liste direkt eine Längenabfrage am Objektkopf ist. len(x) == 0 tut dasselbe, baut danach aber noch eine Ganzzahl und vergleicht. x == [] legt zuerst eine ganze neue leere Liste an und führt dann einen vollständigen Sequenzvergleich durch.

In einer Schleife mit zehn Durchläufen spielt das keine Rolle. Es ist aber angenehm, dass die lesbare Variante zugleich die billige ist.

Was sie sonst noch erfasst

Hier ist der Haken, und den sollte man kennen, bevor man sich auf die Schreibweise verlässt:

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 ist wahr für eine leere Liste, einen leeren String, die Null und None. Diese Funktion kann also nicht unterscheiden zwischen “du hast mir eine leere Liste gegeben” und “du hast mir gar nichts gegeben”:

def verarbeite(elemente=None):
    if not elemente:
        return "nichts zu tun"
process([])   : nothing to do
process(None) : nothing to do

Meistens ist genau das gewollt — beides heißt “keine Arbeit”. Gelegentlich nicht, und dann muss man es hinschreiben:

def verarbeite_streng(elemente):
    if elemente is None:
        return "es wurde keine Liste uebergeben"
    if not elemente:
        return "es wurde eine leere Liste uebergeben"
strict, []   : an empty list was given
strict, None : no list was given

Meine Regel: Wenn None und leer für den Aufrufer dasselbe bedeuten, nimm not elemente. Ist der Unterschied bedeutsam — “Feld fehlt” gegen “Feld da, aber leer”, was bei JSON dauernd vorkommt — dann prüf explizit auf None.

Bei Generatoren funktioniert es nicht

Das ist eine echte Falle, denn es gibt keinen Fehler:

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

Ein Generator ist immer truthy. Er hat keine Länge, und er kann nicht wissen, ob er etwas liefern wird, ohne zu laufen — womit er den Wert verbrauchen würde, den er dabei erzeugt.

if not gen: ist also immer falsch, ganz gleich was der Generator tut. Um herauszufinden, ob etwas darin ist, musst du nach einem Element fragen:

markierung = object()
if next(gen, markierung) is markierung:
    ...   # er war leer
next(empty_gen(), sentinel) is sentinel : True

Beachte, dass das erste Element dabei verbraucht wird — du musst also mit dem gerade geholten Wert weiterarbeiten und darfst nicht von vorne iterieren.

Dasselbe gilt für alles Verzögerte: ein Dateiobjekt, ein map, ein zip, einen Datenbank-Cursor. Wenn du auf Leere prüfen musst, materialisier es mit list() oder bau die Sache so um, dass du es nicht brauchst.

Eigene Klassen bekommen es geschenkt

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

__len__ zu definieren genügt — Python greift darauf zurück, wenn es kein __bool__ gibt. Definierst du beides, gewinnt __bool__. Das ist wissenswert, falls du je einen Container willst, der leer und trotzdem truthy ist.

Ein Hinweis zu numpy und pandas

Wenn elemente ein numpy-Array oder eine pandas-Series sein könnte, wirft if not elemente::

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

Sie weigern sich zu raten, ob “irgendein Element ist wahr” oder “der Container ist nicht leer” gemeint war. Nimm .size == 0 bei numpy oder .empty bei einem pandas-DataFrame beziehungsweise einer Series. Der Artikel über das Iterieren von DataFrames behandelt denselben Fehler von der anderen Seite.

Hinweis zu Netcup (Werbung)

Der deutsche Hoster Netcup bietet unter anderem günstige und zugleich leistungsstarke Webhosting Pakete, KVM-basierte Root Server und dezidierte Server an. Mit unseren Gutscheincodes kannst du noch mehr Geld sparen (6€ bei deiner ersten Bestellung, 30% Rabatt auf alle KVM-basierten Root Server, ...).