Functions
Function Basics
Defining and calling functions, the foundation of Python programming
Interview: Fundamental concept tested in virtually all Python interviews
Functions are the primary building block for organizing code in Python. They allow you to define reusable blocks of logic, improve code readability, and make debugging easier. Understanding function definition, invocation, and the execution model is essential for every Python developer.
Defining Functions
The def keyword creates a function object and binds it to a name:
- Function name: Follows the same rules as variable names — use snake_case by convention
- Parameters: Listed in parentheses — can include positional, keyword, default,
args, and*kwargs - Docstring: Optional but recommended first line — describes what the function does
- Body: Indented block of statements that executes when the function is called
- Return: Optional return statement — if omitted, the function returns None implicitly
Function Execution Model
- Definition time:
defcreates a function object — no code runs yet - Call time: Parentheses after the name trigger execution —
func() - Local frame: Each call creates a new local scope with its own variables
- Stack frames: Nested calls create a call stack — Python's default limit is ~1000 frames
Functions Are Objects
In Python, functions are first-class objects. You can assign them to variables, store them in lists, pass them as arguments, and set custom attributes on them. The def statement is essentially an assignment: it creates a function object and binds it to the function name.
Multiple Return Values
Python functions can return multiple values using tuples. This is commonly used for functions that compute related results:
- Tuple packing:
return a, b, cautomatically packs into a tuple - Tuple unpacking:
x, y, z = func()unpacks the returned tuple - Named tuples: Use
collections.namedtuplefor readable multi-value returns
Best Practices
- Single responsibility: Each function should do one thing and do it well
- Descriptive names: Use verb phrases like
calculate_total()orvalidate_email() - Keep them short: Functions longer than ~20 lines should be broken into smaller functions
- Avoid side effects: Prefer pure functions that don't modify external state
Common Pitfall: Mutable Default Arguments
Never use mutable objects (lists, dicts) as default parameter values. The default is created once at definition time and shared across all calls. Use None as default and create the mutable object inside the function body.
Use Cases
Breaking complex problems into smaller, testable units
Creating reusable utility functions (validation, formatting, conversion)
Implementing dispatch tables for command patterns and state machines
Building callback-based APIs and event handlers
Organizing code into modules with clear interfaces
Common Mistakes
Using mutable default arguments (lists, dicts) that persist between calls
Forgetting that functions without a return statement return None, not undefined
Writing functions that do too many things — violates single responsibility principle
Modifying global state inside functions — makes code hard to test and debug
Not adding docstrings — makes the codebase unmaintainable as it grows