Defining functions and return values
Overview
`def` creates a function object and binds it to a name. Parameters are the placeholder names in the definition; arguments are the actual values passed at call time: def validate_port(port, min_port=1024): return port >= min_port `return` exits the function immediately and sends a value back to the caller. A function with no `return` statement (or a bare `return`) returns `None` — Python does this silently. You can return multiple values by separating them with a comma; Python packs them into a `tuple`: def parse_dsn(dsn): host, port = dsn.rsplit(':', 1) return host, int(port) h, p = parse_dsn('localhost:5432') Never use mutable types like `list` or `dict` as default arguments, because the default value is created only once when the function is defined, causing all calls to share the exact same object. This trap is covered fully in mutable-default-argument: def add_item(item, basket=[]): basket.append(item) return basket Think of a function as a named, reusable machine: you feed arguments in, it processes them, and `return` hands the result back out.
Functions are the primary unit of reuse in Python. Every `FastAPI` route, `Pydantic` validator, and utility helper is a function. Understanding returning `None` vs returning a value is critical — forgetting to `return` a value is a common source of `None`-related bugs.
Where used: `FastAPI` route handlers (every endpoint is a function), `Pydantic` `field_validator` decorators, utility helpers in any Python module
Why learn this
- Every `FastAPI` endpoint is a function — understanding `def`, parameters, and `return` is a baseline requirement
- Returning multiple values (`tuple` unpacking) is used constantly in real backend code to return both a result and a status
Code walkthrough
def build_slug(title, separator='-'):
return title.lower().replace(' ', separator)
result = build_slug('Getting Started')
print(result)
result2 = build_slug('API Reference', separator='_')
print(result2)
Focus: `return` sends the processed value back to the caller; without it, `result` would be `None` — the function would silently discard the work.
Common mistakes
- Forgetting to return a value: `def process(x): x * 2` computes but discards the result; the function returns `None`. Fix: add `return x * 2`.
- Shadowing a built-in name: `def list(...)` or `def id(...)` silently replaces the built-in. Use descriptive domain names like `user_list` or `record_id`.
- Calling the function before defining it: Python executes top-to-bottom at module load time. A call before the `def` raises a `NameError`. Define functions before the code that uses them, or wrap them in a `main()` block.
- Using mutable default arguments: Setting a parameter default to `[]` or `{}` means all calls share the exact same `list` or `dict`. Fix: use `None` as the default and initialize `[]` inside the function.
Glossary
- parameters
- The placeholder names in a function definition that will receive actual values when called. Example: `def add(x, y):`
- arguments
- The actual values passed to a function when it is called. Example: `add(5, 3)`
- tuple
- An ordered, unchanging list of values. Example: `(1, 2, 3)`
- built-in
- A standard Python function or variable that comes out-of-the-box. Example: `len()`
Recall questions
- What does a function return when it has no `return` statement?
- What is the difference between a parameter and an argument?
- How do you return multiple values from a Python function?
- What happens to code that appears after a `return` statement in the same branch?
- Why shouldn't you use a mutable object like a `list` or `dict` as a default argument?
Understanding checks
What will be printed?
`None`
The `greet` function creates a string and assigns it to `message`, but it doesn't `return` anything. By default, Python functions return `None`.
What is the output of this code?
`10`
The function returns `10`. The `print` statement after the `return` is never executed because `return` exits the function immediately.
Practice tasks
DSN parser
Modify the `parse_dsn` function so that it returns both the `host` and the `port` (as an integer) instead of just the host. Currently it only returns the host.
Challenge
Response envelope builder
Write `make_response(data, success=True)` that returns two values: a `dict` `{'data': data, 'ok': success}` and an integer HTTP status code — `200` when `success` is `True`, `400` when `False`. Unpack both return values at the call site and `print` them.
Continue learning
Previous: Primitive types: int, float, bool, str
Previous: if/elif/else and Python truthiness
Previous: Mutable default argument pitfall
Next: *args and **kwargs
Next: LEGB rule: variable scope in Python
Next: Lambda functions and when to use them
Next: First-class functions: passing and returning functions