How do I add default parameters to functions when using type hinting?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Python, default values and type hints use a simple syntax, but the details matter once None, mutable defaults, or static type checkers enter the picture. The goal is to make the function signature truthful: the annotation should describe what callers may pass, and the default should match that contract.
The Basic Syntax
The standard form is:
The pattern is:
- parameter name
- colon and type annotation
- equals sign and default value
That is all you need for many functions.
Match the Type to the Default
If the default is None, the type should say that None is allowed. In modern Python, that usually means str | None, list[int] | None, and similar forms.
In older style typing, the same idea is written with Optional:
The important part is not the spelling. It is keeping the annotation honest. Writing nickname: str = None is misleading because the default is not actually a str.
Never Use Mutable Defaults for Ordinary Data
This is the classic Python trap:
That prints a reused list because the default list is created once when the function is defined, not once per call.
The safe pattern is:
This pattern is so common because it is both runtime-safe and type-checker-friendly.
Keyword-Only Defaults Make APIs Safer
When a function has several optional settings, keyword-only parameters improve readability:
This reduces call-site mistakes because the optional arguments must be named explicitly.
When None Means Something Real
Sometimes None is not the same as "argument omitted." In that case, use a sentinel object instead of overloading None with two meanings.
This is more precise than forcing None to mean both "missing" and "explicitly disabled."
Defaults and Static Type Checkers
Type hints are most useful when tools such as mypy, pyright, or IDE inspections can reason about the function correctly. That means:
- the default value should be compatible with the annotation
- return types should reflect real behavior
- sentinel patterns should be deliberate and documented
For example, this signature is clearer than one that hides optional behavior:
The function always returns bool, and the default stays inside that type.
Common Pitfalls
The biggest mistake is writing a default that does not match the annotation, especially None with a non-optional type.
Another common problem is mutable defaults such as lists and dictionaries. That creates hidden shared state between calls.
Developers also sometimes assume type hints enforce validation at runtime. They do not. If you need runtime checks, add them explicitly or use a validation library.
Finally, keep signatures readable. A technically valid type-hinted function can still be hard to use if too many optional parameters are positional or poorly named.
Summary
- The normal form is
param: Type = default. - If the default is
None, includeNonein the type. - Avoid mutable defaults such as
[]and{}. - Use keyword-only defaults when a function has several optional settings.
- Keep the annotation and the actual runtime behavior aligned so type checkers can help you.

