Abschnitt 7 · Lektion 4
Tabellen als Listen von Dictionaries
Ein Haushaltsbuch ist eine Tabelle. Jede Zeile ist eine Ausgabe, und jede Ausgabe hat dieselben Spalten. An welchem Tag, wofür, wie viel. In einer Tabellenkalkulation stehen die Spalten nebeneinander und haben oben eine Überschrift. In Python gibt es zwei naheliegende Wege, so eine Zeile aufzuschreiben, und der zweite ist der übliche.
Eine Zeile mit Namen
zeile = ("28.09.", "Lebensmittel", 31.80)
print(zeile[2])
zeile = {"datum": "28.09.", "kategorie": "Lebensmittel", "betrag": 31.80}
print(zeile["betrag"])
print(zeile) Als Tupel geht es, und zeile[2] ist der Betrag. Nur musst du dafür wissen, dass der Betrag an
Position 2 steht. Wer den Code in drei Monaten liest, weiß das nicht mehr.
Als Dictionary hat jede Spalte ihren Namen, und bei zeile["betrag"] ist klar, was gemeint ist. Die
Schlüssel sind die Überschriften der Tabelle und die Werte der Inhalt einer Zeile.
Die Spaltennamen stehen in diesem Kurs klein und ohne Umlaute da, wie Variablennamen. Pflicht ist
das nicht. Aber dann musst du nie überlegen, ob die Spalte nun Betrag oder betrag hieß. Wenn du
danebenliegst, gibt es einen KeyError, hier KeyError: 'Betrag'.
Die Tabelle als Liste
ausgaben = [
{"datum": "28.09.", "kategorie": "Lebensmittel", "betrag": 31.80},
{"datum": "29.09.", "kategorie": "Freizeit", "betrag": 18.00},
{"datum": "30.09.", "kategorie": "Mobilität", "betrag": 2.90},
{"datum": "02.10.", "kategorie": "Freizeit", "betrag": 7.50},
{"datum": "03.10.", "kategorie": "Lebensmittel", "betrag": 18.60},
]
print(len(ausgaben))
print(ausgaben[1])
print(ausgaben[1]["kategorie"])
for ausgabe in ausgaben:
print(f"{ausgabe['datum']} {ausgabe['kategorie']:<14}{ausgabe['betrag']:>6.2f}") Die ganze Tabelle ist eine Liste aus solchen Zeilen. Eine Woche Ausgaben ist also eine Liste aus fünf Dictionaries. Damit es lesbar bleibt, steht jedes in einer eigenen Zeile des Codes, wie die Listen über mehrere Zeilen in Lektion 5.1.
Gelesen wird von außen nach innen. ausgaben[1] ist die zweite Zeile der Tabelle, ein ganzes
Dictionary, und ausgaben[1]["kategorie"] ist darin die Kategorie. Zwei Paar eckige Klammern
hintereinander, und mit jedem Paar geht es eine Ebene tiefer. Erst kommt die Position in der Liste,
dann der Schlüssel in der Zeile.
Die Schleife geht die Tabelle Zeile für Zeile durch. In jeder Runde steht in ausgabe ein
Dictionary, und die Spalten liest du über ihre Namen. Im f-String stehen die Schlüssel dabei in
einfachen Anführungszeichen, weil außen doppelte stehen. Das ist die Regel aus den f-Strings, innen
andere als außen.
Filtern und zusammenzählen
ausgaben = [
{"datum": "28.09.", "kategorie": "Lebensmittel", "betrag": 31.80},
{"datum": "29.09.", "kategorie": "Freizeit", "betrag": 18.00},
{"datum": "30.09.", "kategorie": "Mobilität", "betrag": 2.90},
{"datum": "02.10.", "kategorie": "Freizeit", "betrag": 7.50},
{"datum": "03.10.", "kategorie": "Lebensmittel", "betrag": 18.60},
]
summe = 0
anzahl = 0
for ausgabe in ausgaben:
if ausgabe["kategorie"] == "Freizeit":
summe += ausgabe["betrag"]
anzahl += 1
print(f"Freizeit: {anzahl} Ausgaben, zusammen {summe:.2f} Euro")
print(sum([a["betrag"] for a in ausgaben if a["kategorie"] == "Freizeit"])) Filtern und Summieren gehen wie bei einer Liste aus Zahlen. Nur schauen Frage und Rechnung jeweils
auf eine andere Spalte der Zeile. Im if geht es um die Kategorie und bei der Summe um den Betrag.
Nebenbei zählt ein zweiter Zähler mit, wie viele Ausgaben es waren. Das ist das Zählmuster.
In eine List Comprehension passt das auch. Darin werden die Beträge der passenden Zeilen gesammelt,
und sum() zählt sie zusammen. Für eine einzige Zahl ist das bequem. Brauchst du daneben noch die
Anzahl oder sonst etwas, ist die Schleife übersichtlicher.
Die ganze Zeile merken
ausgaben = [
{"datum": "28.09.", "kategorie": "Lebensmittel", "betrag": 31.80},
{"datum": "29.09.", "kategorie": "Freizeit", "betrag": 18.00},
{"datum": "30.09.", "kategorie": "Mobilität", "betrag": 2.90},
{"datum": "02.10.", "kategorie": "Freizeit", "betrag": 7.50},
{"datum": "03.10.", "kategorie": "Lebensmittel", "betrag": 18.60},
]
print([a["betrag"] for a in ausgaben if a["kategorie"] == "Freizeit"])
erste = None
for ausgabe in ausgaben:
if ausgabe["kategorie"] == "Freizeit":
erste = ausgabe
break
print(f"Zuerst Freizeit: {erste['betrag']:.2f} Euro am {erste['datum']}")
print(min([a["betrag"] for a in ausgaben])) Mit einer List Comprehension hast du die Beträge für Freizeit schnell eingesammelt, 18,00 und 7,50 Euro. Nur weißt du danach nicht mehr, an welchem Tag sie anfielen, denn in der Liste stehen nur noch die Zahlen und nicht mehr die Zeilen, aus denen sie kamen.
Deshalb wird in der Schleife danach nicht der Betrag gemerkt, sondern die ganze Zeile. Die erste
Zeile für Freizeit landet in erste, und danach ist mit break Schluss. Am Ende steht in erste
ein ganzes Dictionary, und daraus kommen Betrag und Datum. Das None davor ist für eine Woche ohne
Freizeit da. Dann steht in erste eben nichts, statt dass der Name ganz fehlt.
Dasselbe Problem hat min() in der letzten Zeile. Es findet 2,90 Euro als kleinste Ausgabe, aber
nicht, wann das war und wofür. Wenn du die kleinste oder die größte samt Datum brauchst, merkst du
dir auch dort die ganze Zeile, nur hört die Schleife dann nicht beim ersten Treffer auf. Die Idee
ist dieselbe wie beim teuersten Tag in Lektion 4.3. Dort waren es zwei Dinge in zwei Namen, hier ist
es eins, in dem alles drinsteht.
Liste oder Zeile
ausgaben = [
{"datum": "28.09.", "kategorie": "Lebensmittel", "betrag": 31.80},
{"datum": "29.09.", "kategorie": "Freizeit", "betrag": 18.00},
]
print(ausgaben[0]["betrag"])
print(ausgaben["betrag"]) Der häufigste Fehler mit solchen Tabellen ist, die Ebenen zu verwechseln. ausgaben["betrag"] fragt
die ganze Liste nach einem Betrag, und eine Liste hat keine Schlüssel, nur Positionen. Heraus kommt
TypeError: list indices must be integers or slices, not str, auf Deutsch „Positionen einer Liste
müssen ganze Zahlen oder Ausschnitte sein, kein Text“. Gemeint war der Betrag einer Zeile, und an
den kommst du über eine Position oder in der Schleife.
So sehen Daten übrigens aus, wenn Python sie aus einer Tabellendatei liest. In Abschnitt 12 kommen
Tabellen aus CSV-Dateien, und heraus kommt genau so eine Liste von Dictionaries. Bei CSV sind die
Werte darin erst einmal Text. Zu Zahlen werden sie wie in der Aufgabe dieser Lektion mit float().
Was die Aufgabe will
Eine Woche Haushaltsbuch steht in einer Datei, eine Ausgabe je Zeile, und der Startcode macht daraus schon eine Liste von Dictionaries. Gesucht sind zwei Antworten. Wie viel ist in dieser Woche für Lebensmittel draufgegangen? Und welches war die größte einzelne Ausgabe, mit Datum und Kategorie?
Zum Mitnehmen
In Python wird eine Tabelle zu einer Liste von Dictionaries. Die Zeilen sind Dictionaries, und die Spaltennamen sind ihre Schlüssel. Eine Schleife geht die Zeilen durch, und die Spalten liest du über ihren Namen statt über eine Position.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.
Was in dieser Lektion steckt
-
Artikel mit 5 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe, dein Code läuft auf einem Server
Öffnet sich mit dem Basis Konto.