Listenverständnisse (list comprehensions) sind eine prägnante Möglichkeit, Listen basierend auf vorhandenen iterierbaren Objekten mithilfe einer kurzen Syntax zu erstellen:
squares = [x**2 for x in range(10)]
Diese Notation ist äquivalent zu:
squares = [] for x in range(10): squares.append(x**2)
Listenverständnisse haben mehrere Vorteile:
evens = [x for x in range(10) if x % 2 == 0];Analog zu map():
def f(x): return x**2 squares = list(map(f, range(10)))
map ist schneller bei großen Daten, wenn eine bereits in C vorhandene Funktion verwendet wird, und eignet sich für die Anwendung einer Funktion auf alle Elemente. List comprehension ist für beliebige Ausdrücke geeignet, nicht nur für vorhandene Funktionen. Die for-Schleife ist flexibler, aber umfangreicher.
Warum ist die Variable x nach der Ausführung der Liste in dem Ausdruck
[x for x in range(10)]in Python2 außerhalb des Ausdrucks zugänglich, aber nicht in Python3?
Antwort: In Python2 behält die Schleifenvariable (x) ihren Wert nach der Ausführung des List Comprehensions. In Python3 wird sie "isoliert" und ist außerhalb der Liste nicht zugänglich, was unerwünschte Nebeneffekte verhindert.
Beispiel:
# Python 2.x: [x for x in range(3)] print(x) # x == 2 # Python 3.x: [x for x in range(3)] print(x) # NameError: name 'x' is not defined
Geschichte 1
Ein Entwickler in einem großen Projekt wollte einen neuen Filter erstellen und eine neue Liste über list comprehension generieren:
my_list = [item.transform() for item in data if item.is_valid()]
Aber der Vorgang item.transform() verursachte einen Fehler, wenn item.is_valid() False zurückgab. Die Prüfungsfunktion war jedoch mit möglichen Nebeneffekten geschrieben, und letztendlich störte das Listenverständnis unerwartet Teile des Codes mit Nebenwirkungen.
Geschichte 2
Im Projekt gab es bei der Migration von Python2 auf Python3 einen Entwickler, der sich sicher war, dass die Schleifenvariable verfügbar bleibt:
[x for x in range(5)] print(x) # Erwartete 4, erhielt aber einen NameError.
Das führte zu einem Bug in der zyklischen Logik, wo die Variable außerhalb des Comprehensions benötigt wurde.
Geschichte 3
Die Verwendung von verschachtelten Listenverständnissen ohne explizite Angabe der Ebenen:
def flatten(matrix): return [cell for row in matrix for cell in row]
Anfänger machen häufig Fehler aufgrund einer falschen Reihenfolge in der Durchlauf (z.B. [cell for cell in row for row in matrix] oder überflüssige Verschachtelung), was zu einem falschen Ergebnis führt – ein eindimensionaler statt eines zweidimensionalen oder umgekehrt.