Direkt zum Hauptinhalt springen
eLearner.app
Modul 8 · Lektion 3 von 431/36 im Kurs~12 min
Lektionen des Moduls (3/4)

collections: Counter und defaultdict

Das Modul collections fügt spezialisierte Datentypen hinzu, die die integrierten Collections erweitern. Die drei am häufigsten verwendeten: Counter, defaultdict, namedtuple.

Counter: Häufigkeitszählung

Python
from collections import Counter

parole = ["mela", "pera", "mela", "kiwi", "mela", "pera"]
c = Counter(parole)
# Counter({'mela': 3, 'pera': 2, 'kiwi': 1})

c["mela"]            # 3
c["banana"]          # 0   (default for missing keys, NO KeyError)
c.most_common(2)     # [('mela', 3), ('pera', 2)]

Er funktioniert auch bei Strings (zählt Zeichen):

Python
Counter("ciao mondo")
# Counter({'o': 2, 'c': 1, 'i': 1, 'a': 1, ' ': 1, 'm': 1, 'n': 1, 'd': 1})

Er unterstützt mengenähnliche Operationen auf Zählungen (+, -, &, |) – sehr praktisch, um Zählungen aus verschiedenen Quellen zu aggregieren.

defaultdict: Dictionary mit automatischem Standardwert

Ein Dictionary, das beim Zugriff auf einen fehlenden Schlüssel diesen durch Aufruf einer Factory erstellt.

Python
from collections import defaultdict

gruppi = defaultdict(list)        # factory = list (empty list)
for nome in ["Ada", "Linus", "Ada", "Grace"]:
    gruppi[nome].append(1)
# defaultdict(list, {'Ada': [1, 1], 'Linus': [1], 'Grace': [1]})

Ohne defaultdict müsstest du Folgendes schreiben:

Python
gruppi = {}
for nome in [...]:
    if nome not in gruppi:
        gruppi[nome] = []
    gruppi[nome].append(1)

Häufige Factories: list, int (Standardwert 0), set, dict.

namedtuple: Tupel mit Feldnamen

Eine leichtgewichtige Methode, um unveränderliche Datensatzklassen zu erstellen. Es ist ein Tupel, aber mit Feldzugriff über Namen.

Python
from collections import namedtuple

Punto = namedtuple("Punto", ["x", "y"])
p = Punto(3, 4)
p.x          # 3 (access by name)
p[0]         # 3 (access by index, still a tuple)
p.x + p.y    # 7

# typical use: return multiple values from a function
def divisione(a, b):
    Risultato = namedtuple("Risultato", ["quoziente", "resto"])
    return Risultato(a // b, a % b)

r = divisione(17, 5)
r.quoziente   # 3
r.resto       # 2

(Für komplexere Fälle gibt es seit 3.7 auch dataclasses – siehe M9.)

namedtuple: Leichtgewichtige unveränderliche Datensätze

Das Modul collections exportiert auch namedtuple, mit dem du schnell leichtgewichtige klassenähnliche Objekte zum Speichern strukturierter Daten erstellen kannst, ohne Konstruktoren oder Boilerplate-Methoden schreiben zu müssen:

Python
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x, p.y)

Probiere es aus

Übung#python.m8.l3.e1
Versuche: 0Wird geladen…

Berechne aus der Liste `words = ['mela', 'pera', 'mela', 'kiwi', 'mela', 'pera']` das am häufigsten vorkommende Wort als String in `top`. Evaluiere `top`.

Editor wird geladen…
Hinweis anzeigen

Counter(...).most_common(1) gibt [(Wort, Anzahl)] zurück.

Lösung nach 3 Versuchen verfügbar

Wiederholungsübung

Übung#python.m8.l3.e2
Versuche: 0Wird geladen…

Erstelle für die Studenten `enrollments = [('Ada', 'mate'), ('Linus', 'fisica'), ('Ada', 'storia'), ('Grace', 'mate')]` `courses_per_student` als defaultdict(list). Evaluiere `dict(courses_per_student)`.

Editor wird geladen…
Hinweis anzeigen

defaultdict(list), dann for s, c in enrollments.

Lösung nach 3 Versuchen verfügbar

Zusätzliche Herausforderung

Übung#python.m8.l3.e3
Versuche: 0Wird geladen…

Importiere `Counter` aus `collections`. Zähle die Häufigkeit der Zeichen im String `text = "abracadabra"`. Speichere den Zähler in `char_counter` und evaluiere ihn.

Editor wird geladen…
Hinweis anzeigen

Counter nimmt den String als Parameter und zählt das Vorkommen jedes Buchstabens.

Lösung nach 3 Versuchen verfügbar