Abschnitt 7 · Lektion 3
Zählen mit Dictionaries
Am Kaffeestand beim Vereinsfest willst du wissen, wie oft Kaffee bestellt wurde, wie oft Tee und wie oft Kakao. Und vielleicht bestellt nachher noch jemand eine Limo, an die vorher keiner gedacht hat.
Ein einzelner Zähler, der vor der Schleife auf null steht und darin um eins wächst, reicht dafür nicht. Für jedes Getränk eine eigene Variable geht aber auch nicht. Du weißt ja vorher gar nicht, welche Getränke es geben wird.
Mit einem Dictionary geht es. Jedes Getränk bekommt seinen eigenen Zähler, als Wert unter seinem Namen, und ein Getränk, das neu auftaucht, bekommt eben einen neuen.
Das Zählmuster
bestellungen = ["Kaffee", "Tee", "Kaffee", "Kakao", "Kaffee", "Tee"]
zaehler = {}
for getraenk in bestellungen:
zaehler[getraenk] = zaehler.get(getraenk, 0) + 1
print(zaehler) Die eine Zeile in der Schleife ist schon das ganze Muster. Python rechnet erst die rechte Seite des Gleichheitszeichens aus und legt das Ergebnis dann links ab. In dieser Reihenfolge liest man die Zeile auch am besten.
zaehler.get(getraenk, 0)holt den bisherigen Stand dieses Getränks. Ist es noch gar nicht da, ist der Stand 0, denn das ist der Standardwert vonget.+ 1zählt die Bestellung dieser Runde dazu.zaehler[getraenk] = …legt den neuen Stand unter dem Namen ab. Beim ersten Kaffee entsteht so ein neues Paar, bei jedem weiteren bekommt das vorhandene einen neuen Wert.
Es ist dasselbe wie anzahl += 1, ausgeschrieben anzahl = anzahl + 1. Nur steht vor dem
Gleichheitszeichen kein fester Name, sondern ein Platz im Dictionary, der vom Getränk der Runde
abhängt.
Wenn du das Beispiel im Reiter Debug aufzeichnest, siehst du das Dictionary wachsen. Die
Schleife springt zwischen Zeile 3 und Zeile 4 hin und her, und vor jeder Zeile 4 steht da, wie weit
gezählt ist. Erst {}, dann {'Kaffee': 1}, dann {'Kaffee': 1, 'Tee': 1}. In der vierten Runde
ist getraenk zum ersten Mal 'Kakao', und einen Schritt später hat das Dictionary ein drittes
Paar. Am Ende stehen drei Zähler darin. Mehr Variablen als zaehler waren dafür nicht nötig.
Plus eins auf nichts
bestellungen = ["Kaffee", "Tee", "Kaffee"]
zaehler = {}
for getraenk in bestellungen:
zaehler[getraenk] += 1
print(zaehler) Die kürzere Form liegt nahe, und sie geht schief. zaehler[getraenk] += 1 heißt ausgeschrieben
zaehler[getraenk] = zaehler[getraenk] + 1, und rechts steht ein Lesen mit eckigen Klammern. Beim
allerersten Kaffee gibt es den Schlüssel noch nicht. Also kommt KeyError: 'Kaffee', gleich in der
ersten Runde. Diese Lücke füllt der Standardwert von get.
Dasselbe mit in
bestellungen = ["Kaffee", "Tee", "Kaffee", "Kakao", "Kaffee", "Tee"]
zaehler = {}
for getraenk in bestellungen:
if getraenk in zaehler:
zaehler[getraenk] += 1
else:
zaehler[getraenk] = 1
for getraenk in sorted(zaehler):
print(f"{getraenk}: {zaehler[getraenk]}") Ist dir die eine Zeile zu dicht, schreibst du es mit in und if. Gibt es das Getränk schon, wird
sein Zähler um eins größer. Sonst fängt es bei 1 an. Hier ist += 1 erlaubt, weil es in dem Zweig
steht, in dem der Schlüssel sicher da ist.
Das Ergebnis ist dasselbe, und beide Formen sind richtig. Die mit get ist kürzer, deshalb sieht
man sie in fremdem Code am häufigsten.
In der zweiten Schleife wird das Ergebnis sortiert ausgegeben. Dass Kakao vor Tee steht, liegt am Alphabet und nicht an den Bestellungen.
Python bringt fürs Zählen übrigens ein fertiges Werkzeug mit, Counter (Zähler). Damit passt die
ganze Schleife in eine Zeile. Es kommt in Lektion 10.1, wenn es um die Werkzeuge geht, die Python
von Haus aus mitbringt, und im Inneren tut es nichts anderes als dieses Muster.
Der Wörterzähler aus Lektion 1.1
text = """Wer den letzten Kaffee nimmt, kocht neuen Kaffee.
Wer den letzten Becher nimmt, spült ihn auch."""
zaehler = {}
for wort in text.lower().split():
wort = wort.strip(".,")
zaehler[wort] = zaehler.get(wort, 0) + 1
for wort, anzahl in zaehler.items():
if anzahl > 1:
print(wort, anzahl) Ganz am Anfang des Kurses stand ein Programm mit dem Versprechen, dass du es sechs Abschnitte später liest wie einen Einkaufszettel. Hier ist es noch einmal, unverändert. Inzwischen kennst du jedes Teil davon.
- Der Text steht in drei Anführungszeichen, weil er über zwei Zeilen geht.
text.lower().split()macht alles klein und zerlegt den Text an Leerraum in Wörter.wort.strip(".,")nimmt Punkt und Komma vom Rand.- Die Zeile mit
getist das Zählmuster von oben. - Die zweite Schleife geht mit
items()durch Wort und Anzahl und gibt nur aus, was mehr als einmal vorkommt.
Heraus kommen fünf Wörter, jedes zweimal: wer, den, letzten, kaffee und nimmt. Am
unscheinbarsten ist dabei die Zeile mit strip. Ohne sie stünde nimmt, mit seinem Komma in der
Ausgabe, und kaffee würde ganz fehlen, weil es einmal ohne Satzzeichen im Text steht und einmal
mit Punkt, und kaffee. wäre für das Dictionary ein eigenes Wort mit einem eigenen Zähler.
Was die Aufgabe will
Ein Verein fragt seine Mitglieder, wohin der nächste Ausflug gehen soll, und jede Antwort ist eine Zeile in einer Datei. Die Antworten wurden von Hand abgetippt und sind entsprechend nicht ganz einheitlich geschrieben. Gezählt werden soll, wie oft jedes Ziel genannt wurde. Ausgegeben werden die Ziele nach dem Alphabet, jedes mit seiner Anzahl.
Zum Mitnehmen
Mit einem Dictionary zählst du viele Dinge auf einmal, jedes unter seinem eigenen Namen, und zwar mit zaehler[ding] = zaehler.get(ding, 0) + 1. Beim allerersten Mal gibt es den Schlüssel noch nicht, und dafür ist der Standardwert 0 da. Mit += 1 allein gäbe es an der Stelle einen KeyError.
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 4 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe, dein Code läuft auf einem Server
Öffnet sich mit dem Basis Konto.