Python Functions: Deep Dive into Arguments & Parameters

What are Python Functions?
A Python function is a named, reusable block of code that performs a specific task, accepts inputs (parameters), and optionally returns an output. Functions are the primary tool for organising logic, avoiding repetition, and making code testable.
Introduction to Python Functions
A function is a reusable block of code designed to perform a single, related action. Functions provide better modularity for your application and a high degree of code reusability.
As you’ve already seen, Python gives you many built-in functions like print() and len(), but you can also create your own functions—these are called user-defined functions.
Why Use Functions?
- Reusability: Write once, use many times. This saves space and prevents "copy-paste" errors.
- Modularity: Break down complex problems into smaller, manageable chunks. This makes debugging much easier.
- Abstraction: Once a function is defined, you only need to know its input and output, not the complex logic inside. It acts as a "black box."
Defining a Function in Python
To define a function, you use the def keyword followed by the function name and parentheses ().
The Basic Structure:
defKeyword: Starts the function definition.- Function Name: A unique identifier for the function.
- Parameters: Inputs listed inside the parentheses (optional).
- Docstring: An optional string describing what the function does.
- Indented Block: The actual logic of the function.
returnStatement: Sends a result back to the caller.
Pro Tip: Docstrings
Always include a docstring for your functions. It helps other developers (and your future self) understand the purpose of the code without reading the logic.
Function Arguments & Parameters
Arguments are the values passed into the function when it is called. Python uses Call by Object Reference, meaning:
- Immutable Objects (int, str, tuple): Behave like "Pass by Value." Changes inside the function don't affect the original.
- Mutable Objects (list, dict): Behave like "Pass by Reference." Changes inside the function will affect the original.
Types of Arguments
| Type | Description |
|---|---|
| Required | Must be passed in the correct positional order. |
| Keyword | Passed with an identifier (key=value), allowing any order. |
| Default | Have a predefined value if no argument is provided. |
| Variable Length | Handle an arbitrary number of inputs using *args and **kwargs. |
1. Required & Keyword Arguments
2. Variable Length Arguments: *args and **kwargs
Sometimes you don't know how many arguments will be passed. Python handles this with:
*args: Receives arguments as a Tuple.**kwargs: Receives arguments as a Dictionary.
3. Special Parameters (Python 3.8+)
Python allows you to restrict how arguments are passed:
- Positional-Only (
/): Parameters before/must be positional. - Keyword-Only (
*): Parameters after*must be keyword-based.
Anonymous Functions: Lambda Expressions
A Lambda function is a small, one-line function without a name. They are often used for short-lived tasks or as arguments to higher-order functions like sort().
Caution with Mutable Defaults
Avoid using mutable objects like empty lists `[]` or dictionaries `{}` as default arguments. They are initialized only once, meaning data will persist between multiple function calls!
4. Default Arguments and Type Hints
Default arguments make parameters optional by supplying a fallback value. Type hints (Python 3.5+) document the expected types without enforcing them:
Type hints are especially useful in larger codebases and are read by tools like mypy and editors like VS Code for autocomplete.
5. Higher-Order Functions
Functions in Python are first-class objects — you can pass them as arguments, return them, or store them in variables. This enables powerful patterns:
Real-World Example: A Data Validator
Combining everything — default args, *args, type hints, and return values:
Related Python Topics
- Python Scope and LEGB Rule — understand variable visibility inside functions
- Python Loops and Iterations — combine loops with functions for data processing
- Python OOP Overview — functions inside classes become methods
- Exception Handling in Python — use try/except inside functions for robust code
For the official reference, see the Python Functions documentation and the section on lambda expressions.
Conclusion
Functions are the building blocks of any robust Python application. By mastering parameters, arguments, and return types, you can write cleaner, more efficient, and modular code.
What's Next?
Move on to Python Scope & LEGB Rule to understand how variables are accessed within and outside these functions.
Common Mistakes with Python Functions and Parameters
1. Mutable default arguments
Defining def append_item(item, lst=[]) creates a single list shared across all calls. The default is evaluated once when the function is defined, not on each call. The fix is def append_item(item, lst=None) with lst = lst if lst is not None else [] inside the body. This is one of the most frequently cited Python gotchas — see Python's common pitfalls.
2. Modifying a list argument in place
When you pass a list to a function and mutate it with .append(), .sort(), or index assignment, the change is visible to the caller because Python passes object references. If mutation is unintended, create a copy: lst = lst[:] or lst = list(original) at the start of the function.
3. Using *args and **kwargs without documenting them
*args collects positional overflow into a tuple; **kwargs collects keyword overflow into a dict. Functions that accept both become hard to call without documentation. Always add a docstring explaining which keys **kwargs expects, or replace open-ended **kwargs with explicit named parameters when the set of options is known.
4. Calling keyword-only arguments positionally
After a bare * in a function signature — def f(a, *, b) — b must always be passed as a keyword argument. Attempting f(1, 2) raises a TypeError. This is intentional: keyword-only arguments make call sites self-documenting. See PEP 3102 — Keyword-Only Arguments.
5. Forgetting that functions are first-class objects
A function defined with def is an object that can be stored in a variable, passed as an argument, or returned from another function. Forgetting this leads to verbose code where a simple map(str, numbers) or sorted(items, key=lambda x: x.date) would suffice. The Python functional programming HOWTO covers these patterns.
Frequently Asked Questions
What is the difference between *args and **kwargs?
*args captures any number of positional arguments beyond the named parameters into a tuple. **kwargs captures any number of keyword arguments into a dictionary. They are used together to write flexible functions that accept variable input, such as decorators and wrapper functions. You can name them anything — *args and **kwargs are conventions, not keywords. The Python function definition syntax documents all parameter forms.
What is a lambda function and when should I use it?
A lambda is an anonymous single-expression function: square = lambda x: x ** 2. Use lambdas for short, throwaway functions passed to higher-order functions like sorted, map, and filter. Avoid lambdas for anything complex enough to warrant a name or a docstring — use a regular def in those cases. The Python lambda expressions documentation explains the restrictions (no statements, single expression only).
How do I return multiple values from a Python function?
Return a tuple: return x, y (the parentheses are optional). The caller can unpack it: a, b = my_function(). For functions returning many values, a namedtuple or dataclass makes the return value self-documenting: return Point(x=1, y=2). See the collections.namedtuple documentation for a lightweight alternative to a full class.
