Functions
🧩 Functions
return, and how variable scope actually works inside a function body.
🛠️ Defining and Calling Functions
Like everything else in Python, the function body is defined by indentation, not braces — the same rule that's applied to every if, for, and while block since Chapter 3.
📥 Parameters: Positional, Keyword, and Default
Calling with name=... instead of relying on position is a keyword argument — it makes the call self-documenting and lets you skip default parameters you don't need to override, or reorder arguments freely.
📦 *args and **kwargs
Sometimes you don't know in advance how many arguments a function will receive. *args collects extra positional arguments into a tuple; **kwargs collects extra keyword arguments into a dictionary:
The names args and kwargs are convention, not a language rule — * and ** are what actually matter. You'll see *args, **kwargs constantly in real Python code, especially in functions designed to wrap or forward calls to other functions.
↩️ Return Values
"Returning multiple values" is really just returning a single tuple that gets unpacked at the call site — the same tuple mechanics from Chapter 6, not a separate language feature.
🔍 Scope
A default value like basket=[] is evaluated exactly once, when the function is defined — not fresh on every call. Since lists are mutable (Chapter 6), every call that relies on the default ends up sharing and mutating the same list. The standard fix is basket=None, then if basket is None: basket = [] inside the function body.
Function Parameters: Go vs Kotlin vs Python
| Feature | Go | Kotlin | Python |
|---|---|---|---|
| Default parameter values | Not supported — simulate with variadic params or a config struct | Supported directly, same idea as Python | Supported directly |
| Keyword/named arguments | Not supported | Supported directly (named arguments) | Supported directly |
| Variadic parameters | func f(nums ...int) | fun f(vararg nums: Int) | def f(*args) |
Kotlin's default and named parameters map almost one-to-one onto Python's — this is one of the friendlier corners of the language to pick up coming from Kotlin. Go's lack of both is a real, common source of friction going the other direction.
def / return
Defines a function; a missing return implicitly returns None.
Default & keyword args
def f(x, y=default); call with f(y=1, x=2) in any order.
*args / **kwargs
Collect extra positional args into a tuple, extra keyword args into a dict.
Scope
Assigning inside a function creates a local variable by default; global opts out of that.
💻 Coding Challenges
Challenge 1: Flexible Greeting
Write a function greet(name, greeting="Hello") that returns f"{greeting}, {name}!". Call it three ways: with just a name, with both arguments positionally, and with both arguments as keyword arguments in reversed order.
Goal: Get comfortable with default values and keyword-argument calling in practice.
Challenge 2: Variadic Average
Write a function average(*args) that returns the average of however many numbers it's called with. Call it with 2 numbers, then again with 5 numbers.
Goal: Practice writing and calling a function with *args.
Challenge 3: Fix the Mutable Default Bug
Given the buggy add_item(item, basket=[]) function from this chapter's warning box, rewrite it correctly using the basket=None pattern so that each call without a basket argument gets its own fresh, independent list.
Goal: Apply the fix for the mutable-default-argument gotcha directly, not just recognize it.
🎯 What's Next
Next chapter: Modules & Packages — import, pip, and virtual environments (venv).