Antwoorden — Hoofdstuk 6: Functies en modulair denken
Opmerking: Code is in het Engels, met korte Nederlandse toelichting erboven of eronder.
Antwoord 1 — Begroeting als functie
from typing import Final
def greet(name: str) -> str:
return f"Hello, {name}!"
if __name__ == "__main__":
print(greet("Ava"))
print(greet("Bo"))
Antwoord 2 — Oppervlakte cirkel (docstring + hints)
import math
def circle_area(radius: float) -> float:
"""Return circle area given a radius.
- Uses math.pi.
- radius must be >= 0 (negative radii don't make physical sense).
"""
if radius < 0:
raise ValueError("radius must be >= 0")
return math.pi * (radius ** 2)
if __name__ == "__main__":
for r in (0.0, 1.5, 2.0):
print(r, circle_area(r))
Antwoord 3 — Standaard exponent
def power(base: float, exp: int = 2) -> float:
return base ** exp
print(power(3)) # 9 (default exp=2)
print(power(3, 3)) # 27
print(power(base=2, exp=5))# 32
Antwoord 4 — Vroege return (guard)
def safe_div(a: float, b: float) -> float | None:
if b == 0:
return None
return a / b
print(safe_div(10, 2)) # 5.0
print(safe_div(3, 0)) # None
Antwoord 5 — Meerdere waarden (min, max, avg)
- We kiezen voor
raise ValueErrorbij lege input en documenteren dat.
from typing import Iterable, Tuple
def min_max_avg(values: list[float]) -> tuple[float, float, float]:
"""Return (min, max, avg) for non-empty list of floats.
Raises ValueError if values is empty.
"""
if not values:
raise ValueError("values must not be empty")
return min(values), max(values), sum(values) / len(values)
print(min_max_avg([3.0, 8.0, 2.0, 7.0]))
Antwoord 6 — Invoer-helper zonder print in kernfunctie
def parse_float(text: str) -> float | None:
try:
return float(text.strip().replace(",", "."))
except ValueError:
return None
if __name__ == "__main__":
raw = input("Enter a number: ")
value = parse_float(raw)
if value is None:
print("Please enter a valid number (use digits, comma or dot).")
else:
print(f"You entered: {value}")
Antwoord 7 — Muteren vs. kopiëren
def append_exclamation_inplace(items: list[str]) -> None:
items.append("!")
def with_exclamation_copy(items: list[str]) -> list[str]:
result = list(items)
result.append("!")
return result
if __name__ == "__main__":
words = ["hello"]
append_exclamation_inplace(words)
print("after inplace:", words) # mutated
words2 = ["hello"]
out = with_exclamation_copy(words2)
print("original:", words2) # unchanged
print("returned:", out)
Antwoord 8 — Scope (LEGB) demonstratie
x = 10 # global
def demo() -> None:
x = 5 # local shadows global x inside this function
print("inside demo:", x)
if __name__ == "__main__":
demo()
print("outside:", x)
# Opmerking: binnen demo() zien we de lokale x=5; buiten blijft x=10.
Antwoord 9 — Docstring en help
def slugify(text: str) -> str:
"""Convert text to a lowercase, dash-separated slug.
Example:
>>> slugify("Hello World!")
'hello-world'
"""
return "-".join(
"".join(ch.lower() for ch in text if ch.isalnum() or ch.isspace()).split()
)
if __name__ == "__main__":
print(slugify.__doc__)
help(slugify) # rendering depends on environment
print(slugify("Hello World!"))
Antwoord 10 — Mutabel standaardargument (slecht vs. goed)
# BAD: default list is created once and reused across calls
def add_item_bad(item, bucket=[]):
bucket.append(item)
return bucket
print(add_item_bad(1)) # [1]
print(add_item_bad(2)) # [1, 2] <-- unexpected accumulation across calls
# GOOD: use None sentinel and create a new list inside
def add_item(item, bucket=None):
if bucket is None:
bucket = []
bucket.append(item)
return bucket
print(add_item(1)) # [1]
print(add_item(2)) # [2] -- independent default per call
Uitdaging (optioneel) — Refactor naar functies
from typing import Iterable
def line_total(qty: int, price: float) -> float:
return qty * price
def format_line(name: str, qty: int, price: float) -> str:
total = line_total(qty, price)
return f"{name:<12}{qty:>4}{price:>9.2f}{total:>9.2f}"
def grand_total(items: list[tuple[str, int, float]]) -> float:
return sum(line_total(q, p) for _, q, p in items)
def render_receipt(items: list[tuple[str, int, float]]) -> str:
lines = [f"{'Item':<12}{'Qty':>4}{'Price':>9}{'Total':>9}"]
for name, qty, price in items:
lines.append(format_line(name, qty, price))
lines.append(f"{'Grand total:':<25}{grand_total(items):>9.2f}")
return "\n".join(lines)
if __name__ == "__main__":
items = [("apple", 3, 0.60), ("banana", 2, 0.50), ("cherry", 10, 0.20)]
print(render_receipt(items))