Optional arguments let callers omit parameters: the function definition supplies a default, so the call stays short. Keyword arguments (name=value) make those skips readable. None is a common default when the “real” default must be built inside the body—especially to dodge mutable shared defaults. For deeper patterns with variadic signatures, see Python *args and **kwargs and Python functions.
Tested on: Python 3.13.3; kernel 6.14.0-37-generic; Ubuntu 25.04.
What are optional arguments in Python?
An optional argument (often called an optional parameter) is a function parameter that has a default value in the def line. Required parameters have no default: callers must supply them. If you skip an optional parameter at call time, Python binds the default. You can still override defaults positionally or by keyword.
| Argument type | Meaning |
|---|---|
| Required | Must be provided (no default in the definition) |
| Optional | Has a default; may be omitted |
| Positional | Matched by order in the call |
| Keyword | Passed as name=value |
Defaults are chosen when the function object is created for literals like 0 or "World"; the default expression runs once, not on every call—important for mutables (see below).
def greet(name, greeting="Hello"):
return f"{greeting}, {name}!"
print(greet("Ada"))
print(greet("Bob", "Hi"))This prints a line for Ada with the default greeting and a line for Bob with Hi.
Default arguments and multiple optional parameters
You can give several parameters defaults. Callers then mix required values with any subset of optionals. When a function grows many knobs, prefer keyword arguments at the call site so readers see which setting is which.
def export(path, fmt="csv", encoding="utf-8", limit=100):
return (path, fmt, encoding, limit)
print(export("data.bin"))
print(export("data.bin", limit=500, fmt="json"))The first call uses all defaults after path; the second overrides limit and fmt by name while keeping encoding.
Required parameters must come before optional ones
Parameters without defaults must appear first in the signature. Putting a non-default after a default is a syntax error.
def bad(a=1, b):
return a + bRunning this as a file fails at parse time: non-default argument follows default argument.
Keyword arguments and optional parameters
Keyword arguments are not the same thing as “optional,” but they pair well: you can skip leading defaults only if later arguments are passed by name (in Python 3.8+ you can also use positional-only and keyword-only markers; the common case is still “required first, then defaults, then keyword calls for clarity”).
| Call style | Best for |
|---|---|
| Positional | Short signatures with an obvious order |
| Keyword | Many optionals, configuration-style calls |
| Mixed | Required values positionally, toggles by name |
def send(host, port=443, timeout=30, retries=3):
return host, port, timeout, retries
# Positional: everything defaults after host
print(send("api.example.com"))
# Keyword: skip port but override timeout
print(send("api.example.com", timeout=60))
# Mixed: set port by position, retries by name
print(send("api.example.com", 8080, retries=1))The three lines print tuples: default HTTPS settings, same port with a longer timeout, and port 8080 with retries set to 1.
Use None as an optional argument default
Use None when “caller did not supply this” must be distinct from a real value such as 0, False, or "", or when the default object must be created per call.
def add_item(item, bucket=None):
if bucket is None:
bucket = []
bucket.append(item)
return bucket
print(add_item("a"))
print(add_item("b"))Each call returns its own one-element list. If bucket=[] were the default, the same list would be reused across calls (Python None)—always use None and assign inside the function for fresh mutables. Check with is None / is not None, not == None.
Optional arguments with *args
*args collects extra positional arguments into a tuple. Use it when the count of positional extras varies (wrappers, small math helpers). Keep variadic functions focused; document what callers may pass.
def total(first, *rest):
return first + sum(rest)
print(total(1, 2, 3))This prints 6.
Optional arguments with kwargs
**kwargs collects unexpected keyword arguments into a dict—handy for forwarding options or plugin-style hooks. Too many hidden keys hurt readability; prefer explicit parameters when the surface is known.
def profile(name, **extra):
return {"name": name, **extra}
print(profile("Ada", role="dev", level=3))Order of parameters in Python functions
Recommended mental model: required parameters, then plain defaults, then *args (if any), then keyword-only parameters (after a bare * if you need them), then **kwargs.
| Piece | Role |
|---|---|
| Required | Core inputs |
| Defaults | Named optional settings |
*args |
Extra positionals |
| Keyword-only | Named options that must not be passed positionally |
**kwargs |
Extra keywords |
Optional defaults vs *args vs kwargs
| Feature | Use when |
|---|---|
| Default argument | You know the name and a fixed default |
| Keyword at call site | You want readable configuration |
*args |
Variable number of positional values |
**kwargs |
Variable or extensible keyword options |
None default |
The real default must be computed per call |
Argument unpacking with optional arguments
*iterable splats a sequence into positional arguments; **dict splats keys into keyword arguments. Useful when arguments are assembled elsewhere.
def line(a, b, c):
return a + b + c
nums = [1, 2]
print(line(*nums, c=3))This prints 6.
Optional arguments in real-world functions
- Formatting helpers: optional
sep,width, orprefixcontrol how text or tables render. - File and data I/O: optional
encoding,delimiter,header, orerrorsmirror what you see in library APIs. - Network or database calls: optional
timeout,retries, or connection flags. - Utilities: optional
max_items,sort_key, ordefaultfor fallbacks.
Prefer explicit parameter names for stable public APIs; reserve *args / **kwargs for thin wrappers or truly open-ended entry points.
Common mistakes with Python optional arguments
- Mutable defaults (
[],{},set()) that share state across calls. - Putting a required parameter after one with a default (syntax error).
- Sprawling optional lists without docstrings or types—call sites become unreadable.
- Confusing “optional parameter” (has a default) with “keyword argument” (call syntax).
- Overusing
*args/**kwargswhere a dataclass or explicit kwargs object would be clearer. - Checking optional
Nonewith== Noneinstead ofis None.
Best practices for optional arguments
- Keep required parameters first; group related defaults together.
- Use clear defaults and document side effects.
- Use keyword arguments at call sites for non-obvious optionals.
- Use
None(or another sentinel) when the default must be created per call. - Split huge signatures into smaller functions or configuration objects when needed.
Python optional arguments quick reference
| Task | Approach |
|---|---|
| Make a parameter optional | Add = default in def |
| Skip at call time | Omit it; Python applies the default |
| Readable calls | Pass optionals by keyword |
| Many positionals | *args |
| Many extra keywords | **kwargs |
| Fresh list or dict default | None + build inside |
| Detect missing optional | is None / is not None |
Summary
- Optional parameters are defined with defaults; callers may omit them.
- Required parameters precede defaulted ones in the
defline. - Keyword calling keeps multi-optional calls readable.
Noneplus in-body initialization avoids shared mutable defaults; test withis None.*argsand**kwargsadd flexibility but should not replace clear names when the contract is fixed.
References
- More on defining functions (official tutorial)
- Function definitions (language reference)

