Een echte partial met vooraf ingevulde keywordargumenten maken.
Voorrang van nieuwe keywordargumenten bij een partial uitleggen.
Een reductie met expliciete beginwaarde ook voor lege invoer laten werken.
Een exportfunctie krijgt steeds hetzelfde formaat mee, maar telkens andere gegevens. Je kunt overal dat formaat herhalen, of een duidelijk benoemde functievariant klaarzetten. De module functools bevat kleine bouwstenen voor dat soort werk met callables.
Een deel van een aanroep voorbereiden
partial maakt een callable met alvast ingevulde argumenten. De oorspronkelijke functie draait nog niet wanneer je de partial aanmaakt. Pas bij een latere aanroep worden de bewaarde en de nieuwe argumenten samengevoegd.
Een keyword dat je later opnieuw meegeeft, vervangt het vooraf ingevulde keyword. Een partial is dus een handige standaardinstelling, geen beveiliging tegen overschrijven. Wil je een waarde echt verplicht vasthouden, dan moet het functiecontract daar afzonderlijk voor zorgen.
De voorbeeldfunctie krijgt zijn eenheid als keyword. De voorbereide callable bewaart meters als standaard, maar een expliciete latere eenheid heeft voorrang. Het oorspronkelijke functieobject blijft voor andere aanroepen beschikbaar.
Een partial heeft onder meer func, args en keywords om de bewaarde onderdelen te bekijken. Hij is een ander soort callable dan de wrapper uit de vorige les. De naam en documentatie worden niet automatisch op dezelfde manier als door wraps overgenomen.
Eén toestand door een reeks dragen
reduce brengt een reeks terug tot één toestand. De stapfunctie ontvangt steeds de vorige toestand en de volgende bronwaarde. Haar retourwaarde wordt de toestand voor de volgende ronde.
De derde parameter is de beginwaarde. Die bepaalt wat er gebeurt als de bron leeg is en voorkomt dat de eerste bronwaarde stilzwijgend als begintoestand wordt gebruikt. Voor vermenigvuldigen past de beginwaarde één: die verandert het eerste product niet.
Een toestand hoeft geen getal te zijn. Een tuple (count, total) kan zowel het aantal als de som bijhouden. Iedere stap maakt dan de volgende tuple met count + 1 en total + value.
Reduce draagt een tuple door iedere stap
from functools import reduce
def step(state, value):
count, total = state
next_state = (count + 1, total + value)
print(next_state)
return next_state
result = reduce(step, iter([5, 8, -1]), (0, 0))
print(result)
print(reduce(step, iter([]), (0, 0)))
Verwachte uitvoer
(1, 5)
(2, 13)
(3, 12)
(3, 12)
(0, 0)
In dit voorbeeld is de toestand een paar getallen en de bron een gewone iterator. De tussenstappen worden hier alleen ter uitleg afgedrukt. De uiteindelijke uitkomst komt van echte opeenvolgende aanroepen door reduce.
Veelgemaakte fout: een beginwaarde vergeten
Een product van niet-lege invoer lijkt zonder beginwaarde soms correct. Bij lege invoer kan reduce dan geen begintoestand kiezen en volgt TypeError. Voor een andere toestandsvorm gaat het nog eerder mis: een los brongetal heeft niet ineens de onderdelen van een tuple.
Kies daarom eerst de betekenis van een lege verwerking. Een leeg product is in deze oefening één; een lege tel-en-somtoestand is (0, 0). Daarmee kun je dezelfde stapfunctie vanaf het eerste element gebruiken.
Helder blijft belangrijker dan kort
Voor alleen een som is sum meestal duidelijker dan reduce. Een gewone lus kan ook beter leesbaar zijn wanneer de toestand veel velden of verschillende foutpaden heeft. Je leert deze hulpmiddelen zodat je hun gedrag kunt herkennen en gericht kunt kiezen.
De oefening vraagt bewust echte partial-objecten voor de twee voorbereide callables. Voor de reducties gebruik je reduce met een beginwaarde en verander je de ontvangen iterable niet. Een generatorbron hoeft niet eerst een lijst te worden.
AAN DE SLAG 0/4
1
Een omrekenfunctie klaarzetten
Vul make_converter(rate) in: geef een echte functools.partial van de meegeleverde convert terug met rate als vooraf ingevuld keyword. Een latere rate of offset moet op de normale partial-manier kunnen worden meegegeven.
2
Keywordstandaarden herbruikbaar maken
Vul bind_defaults(fn, **defaults) in: geef een echte partial die defaults als keywords bewaart, fn pas bij aanroepen uitvoert en latere keywords voorrang geeft.
3
Een product vanaf één opbouwen
Vul product(values) in met reduce: vermenigvuldig de getallen van een eenmaal te doorlopen iterable. Geef 1 voor lege invoer en wijzig de bron niet.
4
Aantal en som samen bijhouden
Vul totals(values) in met reduce: geef de tuple (aantal, som) terug. Begin bij (0, 0), doorloop de bron maar eenmaal en geef ook voor lege invoer die tuple terug.
Samenvatting
partial bewaart argumenten voor een latere echte aanroep.
Een later keyword vervangt het bewaarde keyword met dezelfde naam.
reduce bouwt een toestand op; een beginwaarde maakt lege invoer expliciet.
Hierna meet je kleine bewerkingen herhaaldelijk, zonder één toevallige klokwaarde voor zekerheid aan te zien.