15.1 Functions I: Defining & Calling
Type Hints & Docstrings
Type hints clarify expected types for readers and tooling; docstrings explain purpose and usage.
from typing import Iterable, Tuple
def summarize(nums: Iterable[int]) -> Tuple[int, int, float]:
“””Return (count, total, average) for a series of integers.
Args:
nums: Iterable of integers.
Returns:
A tuple (n, s, avg) where n is element count, s is sum, and avg is mean.
“””
n = 0
s = 0
for x in nums:
n += 1
s += x
avg = s / n if n else 0.0
return n, s, avg
- Use Google- or NumPy-style docstrings for consistency across your project.
- Type hints are optional at runtime but valuable for IDEs, linters, and documentation.
7. Naming, Purity & Side Effects
- Use snake_case for function names (e.g., compute_total).
- Write small, single-purpose functions; one clear responsibility.
- Minimize side effects (mutating globals, printing) unless the function’s purpose is I/O.
- Separate computation from I/O: have one function compute a result and another handle printing.
# Separate concerns: compute vs print
def percent(numerator: int, denominator: int) -> float:
return (numerator / denominator) * 100
def report_percent(numerator: int, denominator: int) -> None:
pct = percent(numerator, denominator)
print(f”{pct:.2f}%”)
8. Common Calling Errors & Diagnostics
- TypeError: wrong number of arguments (missing/extra).
- TypeError: unexpected keyword argument (name mismatch).
- NameError: calling a function before its definition in the same scope (when not yet executed).
# Example: unexpected keyword name
def add(a, b):
return a + b
add(x=1, y=2) # TypeError: add() got an unexpected keyword argument ‘x’
9. Practical Patterns
Patterns you will use frequently when defining/using functions:
- Use defaults to model optional behavior (height=1).
- Provide keyword names for readability at call sites.
- Return tuples for grouped results and unpack at the call site.
- Document preconditions/postconditions in the docstring when non-obvious.
# Example: simple parser returning multiple results
def parse_coordinates(text: str):
“””Parse ‘x,y’ into two ints (x, y). Raises ValueError on bad input.”””
x_str, y_str = text.split(‘,’)
return int(x_str), int(y_str)
x, y = parse_coordinates(‘10,20’)
10. What Comes Next (Preview of Functions II)
- Parameter kinds: positional-only (/), keyword-only (*), variadic *args and **kwargs.
- Mutable default arguments pitfalls and safe patterns.
- Closures, scope rules (LEGB), and decorators overview.