Functions are first-class objects: you can pass them around, return them, and store them — and Python's argument system is unusually flexible.
Defining & returning
def area(w: float, h: float = 1.0) -> float:
"""Return the area of a w × h rectangle."""
return w * h
def min_max(xs):
return min(xs), max(xs) # "multiple" return = one tuple
lo, hi = min_max([4, 1, 9])
print(area(3, 2), area(5), lo, hi) # 6 5.0 1 9
print(area.__doc__) # Return the area of a w × h rectangle.Kinds of parameters
| Kind | Syntax | Call as |
|---|---|---|
| Positional or keyword | def f(a, b) | f(1, 2) or f(b=2, a=1) |
| Default value | def f(a, b=10) | f(1) |
| Variadic positional | def f(*args) | f(1, 2, 3) → args == (1, 2, 3) |
| Variadic keyword | def f(**kwargs) | f(x=1) → kwargs == {'x': 1} |
| Keyword-only | def f(a, *, key) | f(1, key=2) — key must be named |
| Positional-only | def f(a, /, b) | f(1, 2) — a can't be named |
def report(title, *items, sep=", ", **meta):
line = f"{title}: {sep.join(items)}"
if meta:
line += f" {meta}"
return line
print(report("fruits", "apple", "kiwi")) # fruits: apple, kiwi
print(report("ids", "1", "2", sep="|", source="db")) # ids: 1|2 {'source': 'db'}
opts = {"sep": "-"}
print(report("unpacked", *["a", "b"], **opts)) # unpacked: a-bThe mutable default trap
Default values are evaluated once, when def runs — not on each call. A mutable default is shared by every call.
def add_bad(item, bucket=[]):
bucket.append(item)
return bucket
print(add_bad(1), add_bad(2)) # [1, 2] [1, 2]
def add_good(item, bucket=None):
if bucket is None:
bucket = []
bucket.append(item)
return bucket
print(add_good(1), add_good(2)) # [1] [2]How arguments are passed
def mutate(xs):
xs.append(99) # changes the caller's list
def rebind(xs):
xs = [0] # only changes the local name
data = [1]
mutate(data); rebind(data)
print(data) # [1, 99]