A function packages steps under a name so you can reuse and test them. Define it with def, give it parameters, and return a result. A function without return returns None.
Parameters can have default values, and callers can pass arguments by name (keyword arguments), which makes calls easier to read.
Add a docstring (a string on the first line) to explain what the function does, and type hints (score: float -> str) to document the expected types. Python doesn't enforce hints at runtime, but editors and tools like mypy use them to catch mistakes.
def percentage(score: float, out_of: float = 100) -> int:
"""Return score as a whole-number percentage of out_of."""
return round(score / out_of * 100)
def greet(name: str, title: str | None = None) -> str:
if title:
return f"Hello, {title} {name}"
return f"Hello, {name}"
def stats(values: list[float]) -> tuple[float, float, float]:
"""Return (minimum, maximum, average)."""
return min(values), max(values), sum(values) / len(values)
print(percentage(42, 50)) # 84
print(greet("Amina"))
print(greet("Juma", title="Mr.")) # keyword argument
low, high, avg = stats([78, 64, 91]) # unpack the returned tuple
print(f"low={low} high={high} avg={avg:.1f}")
square = lambda n: n * n # tiny anonymous function
print(sorted(["Neema", "Ali", "Baraka"], key=len), square(9))Key points
- One function, one job — small functions are easier to test and reuse.
- Use default values and keyword arguments for readable calls.
- Docstrings and type hints document intent; tools use them to find bugs.
Exercise
Write area_of_rectangle(width, height) and area_of_circle(radius) with type hints and docstrings. Then write describe_area(area, units="cm") that returns a string like "Area: 12.00 cm²".
Show solution
Try the exercise yourself first — then compare your approach with this one.
Each function has type hints and a docstring. math.pi gives π, and describe_area uses a default value for units so callers only pass it when they need something other than centimetres.
import math
def area_of_rectangle(width: float, height: float) -> float:
"""Return the area of a rectangle."""
return width * height
def area_of_circle(radius: float) -> float:
"""Return the area of a circle."""
return math.pi * radius ** 2
def describe_area(area: float, units: str = "cm") -> str:
"""Describe an area to two decimal places, e.g. 'Area: 12.00 cm²'."""
return f"Area: {area:.2f} {units}²"
print(describe_area(area_of_rectangle(3, 4))) # Area: 12.00 cm²
print(describe_area(area_of_circle(2), units="m")) # Area: 12.57 m²