Fijne functies¶
Opdracht: Fijne functies
Opdracht 1: sq(x)¶
def sq(x):
"""Geeft het kwadraat van x terug"""
return x * x
assert sq(5) == 25
assert sq(-3) == 9
assert sq(0) == 0
Het kwadraat is het getal maal zichzelf, dus de berekening past in de returnregel. De derde assertion dekt het randgeval nul, waar de vermenigvuldiging niets meer oplevert dan nul.
Opdracht 2: interp(low, hi, fraction)¶
def interp(low, hi, fraction):
"""Geeft de waarde op fractie fraction tussen low en hi terug"""
return low + (hi - low) * fraction
assert interp(1.0, 9.0, 0.25) == 3.0
assert interp(1.0, 3.0, 0.25) == 1.5
assert interp(24, 42, 0) == 24
assert interp(102, 117, -4.0) == 42.0
(hi - low) is de afstand tussen de twee waarden. Daar een deel van nemen en bij low optellen geeft het antwoord, zonder ook maar één if.
De derde assertion is het randgeval: bij fractie 0 blijf je op low staan. Let op dat er dan 24 uitkomt en niet 24.0 - er is geen enkel floating-point getal bij de berekening betrokken. De vierde laat zien dat een fractie buiten het bereik 0 tot 1 gewoon werkt.
Opdracht 3: checkends(s)¶
def checkends(s):
"""Geeft True als het eerste en het laatste karakter van s gelijk zijn"""
return s[0] == s[-1]
assert checkends("niet gelijk") is False
assert checkends("kijk! wel gelijk") is True
assert checkends("q") is True
assert checkends(" ") is True
Een vergelijking met == levert zelf al True of False op, dus een if-else eromheen voegt niets toe.
Bij een string van één karakter wijzen s[0] en s[-1] naar hetzelfde karakter, en dat is dus altijd True. Dat is het randgeval, en de string met één spatie werkt om dezelfde reden.
Opdracht 4: swap_ends(s)¶
def swap_ends(s):
"""Geeft s terug met het eerste en het laatste karakter verwisseld"""
if len(s) < 2:
return s
return s[-1] + s[1:-1] + s[0]
assert swap_ends("hond") == "donh"
assert swap_ends("python") == "nythop"
assert swap_ends("ab") == "ba"
assert swap_ends("q") == "q"
assert swap_ends("") == ""
De middenstukken haal je met een slice op: s[1:-1] is alles behalve het eerste en het laatste karakter.
Zonder de controle op de lengte gaat het mis bij een string van één karakter: s[0] en s[-1] wijzen dan naar hetzelfde karakter, en swap_ends("q") zou "qq" teruggeven. Precies daarom staat dat geval erbij als assertion.
Opdracht 5: convert_from_seconds(seconds)¶
def convert_from_seconds(seconds):
"""Zet een aantal seconden om naar [dagen, uren, minuten, seconden]"""
days = seconds // (24 * 60 * 60)
seconds = seconds % (24 * 60 * 60)
hours = seconds // (60 * 60)
seconds = seconds % (60 * 60)
minutes = seconds // 60
seconds = seconds % 60
return [days, hours, minutes, seconds]
assert convert_from_seconds(610) == [0, 0, 10, 10]
assert convert_from_seconds(100000) == [1, 3, 46, 40]
assert convert_from_seconds(0) == [0, 0, 0, 0]
assert convert_from_seconds(59) == [0, 0, 0, 59]
Elke stap doet twee dingen: met // de grootste eenheid eruit halen, en met % het restant bewaren voor de volgende stap. Daardoor staat de berekening drie keer in dezelfde vorm en hoef je nergens uit te rekenen wat er al af is.
24 * 60 * 60 blijft staan zoals het is en wordt geen 86400: zo lees je aan de regel zelf af dat het om een dag gaat.
Nul seconden is het randgeval; alle vier de waarden zijn dan nul.