Direct naar de hoofdinhoud
Module 8 · Les 3 van 431/36 in de cursus~12 min
Modulelessen (3/4)

incasso's: Counter en defaultdict

De module collections voegt gespecialiseerde gegevenstypen toe die de ingebouwde collecties. De drie meest gebruikte: Counter, defaultdict, BESCHERMD_INLINE_8.

Counter: frequentietelling

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)]

Het werkt ook op strings (telt tekens):

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

Het ondersteunt set-achtige bewerkingen op tellingen (+, -, &, |) — erg handig voor het aggregeren van tellingen uit verschillende bronnen.

defaultdict: dictaat met automatische standaard

Een dictaat dat, wanneer u toegang krijgt tot een ontbrekende sleutel, deze aanmaakt door een fabriek.

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]})

Zonder defaultdict zou je moeten schrijven:

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

Veelgebruikte fabrieken: list, int (standaard 0), set, dict.

namedtuple: tupels met veldnamen

Een lichtgewicht manier om onveranderlijke recordklassen te creëren. Het is een tupel, maar met veldtoegang op naam.

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

(Voor meer geavanceerde gevallen is er ook dataclasses sinds 3.7 — zie M9.)

genaamdtuple: lichtgewicht onveranderlijke records

De module collections exporteert ook namedtuple, waarmee u snel lichtgewicht, klasse-achtige objecten kunt bouwen om gestructureerde gegevens op te slaan zonder constructors of standaardmethoden te schrijven:

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

Probeer het

Oefening#python.m8.l3.e1
Pogingen: 0Laden…

Gegeven de lijst `words = ['mela', 'pera', 'mela', 'kiwi', 'mela', 'pera']`, berekent u het meest voorkomende woord in `top` als een string. Evalueer 'top'.

Editor laden…
Toon hint

Counter(...).most_common(1) retourneert [(woord, aantal)].

Oplossing beschikbaar na 3 pogingen

Oefening beoordelen

Oefening#python.m8.l3.e2
Pogingen: 0Laden…

Gegeven de studenten `enrollments = [('Ada', 'mate'), ('Linus', 'fisica'), ('Ada', 'storia'), ('Grace', 'mate')]`, bouwt u `courses_per_student` als een standaarddict(lijst). Evalueer `dict(courses_per_student)`.

Editor laden…
Toon hint

defaultdict(list) en vervolgens voor s, c in inschrijvingen.

Oplossing beschikbaar na 3 pogingen

Extra uitdaging

Oefening#python.m8.l3.e3
Pogingen: 0Laden…

Importeer \`Teller\` uit \`verzamelingen\`. Tel de frequentie van de tekens in de string \`text = "abracadabra"\`. Sla de teller op in \`char_counter\` en evalueer deze.

Editor laden…
Toon hint

Counter neemt de string als parameter en telt het aantal keren dat elke letter voorkomt.

Oplossing beschikbaar na 3 pogingen