4.0 What This Teaches
defsyntax: parameters, body, return- Default parameter values and keyword arguments
*argsand**kwargsfor variable-length arguments- Type hints for documentation and tooling
- Functions as first-class objects
- The mutable default argument pitfall
4.1 Defining Functions
def followed by the function name, parenthesized parameters,
and a colon. The body is indented:
def greet(name):
print(f"Hello, {name}!")
def add(a, b):
return a + b
greet("Alice")
result = add(3, 4)
print(result) # 7
return statement returns None
implicitly. Functions can return multiple values as a tuple:
return x, y.
4.2 Default Parameters and Keyword Arguments
def greet(name, greeting="Hello", punctuation="!"):
return f"{greeting}, {name}{punctuation}"
print(greet("Alice")) # Hello, Alice!
print(greet("Bob", greeting="Hi")) # Hi, Bob!
print(greet("Carol", punctuation=".")) # Hello, Carol.
print(greet("Dave", "Hey", ".")) # positional: Hey, Dave.
4.3 *args and **kwargs
def total(*args):
return sum(args)
def show(**kwargs):
for key, value in kwargs.items():
print(f" {key}: {value}")
print(total(1, 2, 3, 4)) # 10
show(name="Alice", age=30, city="Portland")
# name: Alice
# age: 30
# city: Portland
*args collects extra positional arguments into a tuple.
**kwargs collects extra keyword arguments into a dict. You can use
any names, but args and kwargs are the convention.
4.4 Type Hints
def add(a: int, b: int) -> int:
return a + b
def first_positive(values: list[int]) -> int | None:
for v in values:
if v > 0:
return v
return None
mypy and IDE autocompletion to catch type errors
before you run the code. For Python 3.9 and earlier, import from
typing: from typing import List, Optional.
4.5 First-Class Functions
def square(x):
return x * x
def apply(func, values):
return [func(v) for v in values]
results = apply(square, [1, 2, 3, 4])
print(results) # [1, 4, 9, 16]
# Pass a built-in function
words = ["banana", "apple", "cherry"]
words.sort(key=len) # sort by length
print(words) # ['apple', 'banana', 'cherry']
4.6 Mutable Default Arguments
# WRONG - the same list is shared across all calls
def append_to(item, lst=[]):
lst.append(item)
return lst
print(append_to(1)) # [1]
print(append_to(2)) # [1, 2] - unexpected!
# CORRECT - use None as sentinel
def append_to(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
4.7 Example - All Together
# Functions - definitions and calling patterns.
def clamp(value: float, lo: float, hi: float) -> float:
return max(lo, min(hi, value))
def stats(*numbers: float) -> tuple[float, float, float]:
return min(numbers), max(numbers), sum(numbers) / len(numbers)
def repeat(func, n: int):
for _ in range(n):
func()
print(clamp(15, 0, 10)) # 10
print(clamp(-3, 0, 10)) # 0
lo, hi, avg = stats(4, 7, 2, 9, 1)
print(f"lo={lo}, hi={hi}, avg={avg:.1f}")
repeat(lambda: print("tick"), 3)
10
0
lo=1, hi=9, avg=4.6
tick
tick
tick
4.8 Exercise
Exercise
- Write
power(base, exponent=2)that raises base to exponent. Call it with one arg and with two. - Write
summarize(*words)that returns a dict mapping each word to its length. - Write
apply_twice(func, x)that applies func to x twice. Test it with a function that doubles a number.
4.9 Common Mistakes
Mutable default argument
None as the default and create the mutable
object inside the function body.
Forgetting return
def add(a, b):
a + b # expression evaluated but result discarded
result = add(3, 4)
print(result) # None
return statement the function returns None.Confusing *args in definition vs call
def total(*args): # collects extra positional args into a tuple
return sum(args)
nums = [1, 2, 3]
total(*nums) # unpacks the list into positional args
total(nums) # passes the whole list as one arg - wrong!
4.10 Key Terms
| Term | Meaning |
|---|---|
| def | Keyword that introduces a function definition |
| return | Exits the function and optionally provides a value to the caller |
| default argument | Parameter with a fallback value used when the caller omits it |
| keyword argument | Argument passed by name at the call site |
| *args | Collects extra positional arguments into a tuple |
| **kwargs | Collects extra keyword arguments into a dict |
| type hint | Optional annotation (name: type) checked by mypy, not Python |
| first-class function | A function treated as a value: assignable, passable, returnable |
| lambda | An anonymous single-expression function: lambda x: x * 2 |