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)
Frequently Asked Questions
What is the difference between an optional argument and a keyword argument?
An optional argument is a parameter with a default in the def line; a keyword argument is any argument passed by name at call time—you can pass required parameters by keyword too.
Why should mutable defaults use None in Python?
Default objects are created once when the function is defined and reused across calls, so a list or dict default is shared; use None and build a fresh container inside the function body.
Can required parameters come after optional ones in Python?
No—parameters without defaults must appear before parameters with defaults in the function signature, otherwise Python raises a SyntaxError.
When should I use *args and **kwargs?
Use them when the arity or names of extra arguments are unknown or delegated; prefer explicit named parameters when the options are fixed and documented.

