Positional Parameters
The most basic type. Arguments match parameters by position — first argument goes to first parameter, second to second, etc.
def greet(first_name, last_name):
print(f"Hello, {first_name} {last_name}!")
greet("Alice", "Smith") # Alice → first_name, Smith → last_name
greet("Bob", "Jones")
Default Parameter Values
Parameters can have default values — used when the caller doesn't provide that argument.
def power(base, exponent=2): # exponent defaults to 2
return base ** exponent
print(power(5)) # 25 - uses default exponent=2
print(power(5, 3)) # 125 - overrides default
print(power(2, 10)) # 1024
Always put parameters with default values AFTER parameters without defaults, or you get a SyntaxError.
*args – Variable Positional Arguments
*args collects any number of positional arguments into a tuple.
def sum_all(*numbers): # numbers is a tuple
print(f"Received: {numbers}")
return sum(numbers)
print(sum_all(1, 2, 3)) # 6
print(sum_all(10, 20, 30, 40)) # 100
print(sum_all()) # 0 - empty tuple
**kwargs – Variable Keyword Arguments
**kwargs collects any number of keyword arguments into a dictionary.
def print_info(**details): # details is a dict
for key, value in details.items():
print(f" {key}: {value}")
print_info(name="Alice", age=25, city="London")
Parameter Order – The Golden Rule
When combining parameter types, order matters: regular → *args → keyword-only → **kwargs.
# Full parameter order example
def full_function(a, b, c=10, *args, keyword_only=99, **kwargs):
print(f"a={a}, b={b}, c={c}")
print(f"args={args}")
print(f"keyword_only={keyword_only}")
print(f"kwargs={kwargs}")
full_function(1, 2, 3, 4, 5, keyword_only="hello", x=100)
The Mutable Default Argument Trap
This is one of the most famous Python gotchas, and it shows up in real code constantly. A default value is evaluated once, when the function is defined — not each time it's called. So a mutable default (list, dict, set) is shared across every call.
def add_item(item, basket=[]): # ⚠️ default list created ONCE
basket.append(item)
return basket
print(add_item("apple")) # ['apple']
print(add_item("bread")) # ['apple', 'bread'] ← leftover from last call!
The fix is to default to None and build a fresh object inside the function:
def add_item(item, basket=None):
if basket is None:
basket = [] # new list every call
basket.append(item)
return basket
Parameter order rules
Python enforces a strict order when you mix parameter kinds. Break it and you get a SyntaxError.
| Order | Kind | Example |
|---|---|---|
| 1 | Positional / default | def f(a, b=2) |
| 2 | *args (extra positionals) | def f(a, *args) |
| 3 | Keyword-only (after *) | def f(a, *, key) |
| 4 | **kwargs (extra keywords) | def f(a, **kwargs) |
Arguments are passed by object reference: rebinding a parameter inside the function doesn't affect the caller, but mutating a mutable argument does.
🏋️ Practical Exercise
Practice every parameter style:
- Write a
greet(name, greeting="Hello")function using a default parameter. - Write
total(*numbers)that sums any number of positional arguments. - Write
describe(**info)that prints every keyword argument it receives. - Call a function using keyword arguments out of order.
🔥 Challenge Exercise
Build a flexible make_report(title, *sections, author="Anon", **meta) function that prints a title, each section on its own line, the author, and any extra metadata key–value pairs. Call it several ways — with no sections, with many, and with extra metadata — to prove the parameter order rule (positional, *args, keyword-only, **kwargs) works. Bonus: add a keyword-only argument after *args.
📋 Summary
- Parameters are the names in a definition; arguments are the values passed when calling.
- Default values make parameters optional:
def f(x, y=10). *argscollects extra positional arguments into a tuple;**kwargscollects extra keyword arguments into a dict.- The required order is: positional,
*args, keyword-only,**kwargs. - Avoid mutable default arguments — they are created once and shared across calls; use
Noneinstead. - Keyword arguments can be passed in any order and improve call readability.
Interview Questions on Function Parameters
- What is the difference between a parameter and an argument?
- What is the difference between positional and keyword arguments?
- What do
*argsand**kwargsdo? - What is the correct order of parameters in a function definition?
- Why is using a mutable default argument (like
[]) dangerous? - What are keyword-only arguments and how do you require them?
- How do default parameter values work?
Related Topics
FAQ
*args and **kwargs? +*args captures extra positional arguments as a tuple; **kwargs captures extra keyword arguments as a dictionary. The names are convention — the * and ** are what matter.
Default values are evaluated once when the function is defined, so a mutable default like def f(items=[]) is shared across all calls and accumulates changes. Use def f(items=None) and create a new list inside the function.
Positional/required parameters first, then default parameters, then *args, then keyword-only parameters, then **kwargs. Violating this order is a syntax error.
Place parameters after a bare * (or after *args). For example def f(a, *, b) makes b keyword-only, so it must be passed as b=value.

