The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Define a function | def greet(name): return f"Hello, {name}!" | View examples |
| Call a function | message = greet("Ada") | View examples |
| Set a default value | def greet(name, punctuation="!"):
return f"Hello, {name}{punctuation}" | View examples |
| Pass a keyword argument | message = greet(name="Ada", punctuation=".") | View examples |
| Require a positional input | def ratio(value, total, /): return value / total | View examples |
| Require a keyword input | def connect(host, *, timeout=10):
return f"{host}:{timeout}" | View examples |
| Create a fresh default list | def collect(value, items=None):
items = [] if items is None else items
items.append(value)
return items | View examples |
| Collect positional arguments | def total(*values): return sum(values) | View examples |
| Collect keyword arguments | def profile(**fields): return fields | View examples |
| Unpack positional values | result = total(*[4, 6, 10]) | View examples |
| Unpack keyword values | user = profile(**{"name": "Ada", "role": "engineer"}) | View examples |
| Annotate a function | def area(width: float, height: float) -> float:
return width * height | View examples |
| Add a docstring | def area(width, height):
"""Return a rectangle's area."""
return width * height | View examples |
| Return a value | def double(number): return number * 2 | View examples |
| Return several values | def bounds(values): return min(values), max(values) | View examples |
| Pass a callback | labels = list(map(str.upper, ["draft", "ready"])) | View examples |
| Create a small lambda | users.sort(key=lambda user: user["name"]) | View examples |
| Return a closure | def multiplier(factor):
return lambda value: value * factor | View examples |
| Wrap a function | greet = trace(greet) | View examples |
Functions package behavior behind a clear name and interface. Keep each function focused, make required and optional inputs obvious, avoid shared mutable defaults, and use annotations and docstrings to communicate intent without assuming they enforce runtime types.
Step by step
Detailed examples
Define and call a focused function
A def statement creates a function object; its body runs only when the function is called. Parameters receive the supplied arguments, and return hands a result to the caller. Use a descriptive verb-oriented name and keep unrelated side effects outside a calculation function.
def greet(name):
return f"Hello, {name}!"
message = greet("Ada")
print(message) Hello, Ada!Design positional and keyword parameters
Defaults make trailing parameters optional, while keyword arguments clarify calls with several similar values. A slash marks preceding parameters as positional-only, and an asterisk marks following parameters as keyword-only. These boundaries can preserve an API's freedom to rename internal parameters or make important options explicit.
def greet(name, punctuation="!"):
return f"Hello, {name}{punctuation}"
message = greet(name="Ada", punctuation=".")
print(message) Hello, Ada.def ratio(value, total, /):
return value / total
def connect(host, *, timeout=10):
return f"{host}:{timeout}"
print(ratio(3, 4))
print(connect("db.internal", timeout=5)) 0.75
db.internal:5Note: The slash parameter marker requires Python 3.8 or newer.
Avoid shared mutable default values
Default expressions are evaluated once when the def statement runs, not once per call. A list, dictionary, or set used directly as a default would therefore be shared by every omitted call. Use None as a sentinel and allocate the mutable value inside the function instead.
def collect(value, items=None):
items = [] if items is None else items
items.append(value)
return items
print(collect("alpha"))
print(collect("beta"))
print(collect("gamma", ["existing"])) ['alpha']
['beta']
['existing', 'gamma']Collect and unpack flexible arguments
A starred parameter collects extra positional inputs into a tuple, and a double-starred parameter collects extra named inputs into a dictionary. At the call site, the same operators unpack an iterable or mapping. Use flexible signatures when the domain genuinely accepts variable inputs, not to hide a function's required interface.
def total(*values):
return sum(values)
result = total(*[4, 6, 10])
print(result) 20def profile(**fields):
return fields
user = profile(**{"name": "Ada", "role": "engineer"})
print(user) {'name': 'Ada', 'role': 'engineer'}Note: Every key unpacked with double star must be a string acceptable as a keyword name for the target call.
Document intent with annotations and docstrings
Annotations expose metadata for static type checkers, editors, and documentation tools, but Python does not enforce them automatically at runtime. A docstring should state the function's purpose and any important behavior that the signature cannot express clearly.
def area(width: float, height: float) -> float:
"""Return a rectangle's area."""
return width * height
print(area(3.5, 2.0))
print(area.__doc__) 7.0
Return a rectangle's area.Return and unpack results
A return statement ends the current call immediately. Writing comma-separated return expressions creates one tuple, which a caller can unpack into the same number of targets. A function that reaches the end without return produces None, so make that behavior intentional.
def double(number):
return number * 2
print(double(6)) 12def bounds(values):
return min(values), max(values)
lowest, highest = bounds([8, 3, 11, 5])
print(lowest, highest) 3 11Pass functions as data
Functions are objects that can be passed to other functions, stored, and returned. Use a named def when behavior needs documentation or several statements; use a lambda for a short expression that is clearest next to the operation consuming it.
labels = list(map(str.upper, ["draft", "ready"]))
users = [{"name": "Grace"}, {"name": "Ada"}]
users.sort(key=lambda user: user["name"])
print(labels)
print(users) ['DRAFT', 'READY']
[{'name': 'Ada'}, {'name': 'Grace'}]Capture state and wrap behavior
A closure retains access to names from the enclosing function after that outer call returns. A decorator receives a function and replaces the decorated binding with another callable, often a wrapper. Preserve wrapper metadata with functools.wraps in production decorators so introspection and documentation still identify the original function.
def multiplier(factor):
return lambda value: value * factor
double = multiplier(2)
print(double(7)) 14from functools import wraps
def trace(function):
@wraps(function)
def wrapper(*args, **kwargs):
print(f"calling {function.__name__}")
return function(*args, **kwargs)
return wrapper
@trace
def greet(name):
return f"Hello, {name}"
print(greet("Ada")) calling greet
Hello, Adadef trace(function):
def wrapper(*args, **kwargs):
print(f"calling {function.__name__}")
return function(*args, **kwargs)
return wrapper
def greet(name):
return f"Hello, {name}"
greet = trace(greet)
print(greet("Grace")) calling greet
Hello, GraceNote: The @trace form is syntactic sugar for this rebinding and is normally clearer directly above the function definition.
Local code tester
Try Python function interfaces
Edit and run the functions locally to practice defaults, keyword-only parameters, callbacks, and return values.
Press Run to load Python locally.
Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
- Python Software FoundationMore Control Flow Tools — Defining Functionsdocs.python.org
- Python Software FoundationCompound statements — Function definitionsdocs.python.org
- Python Software FoundationBuilt-in Functionsdocs.python.org
- Python Software Foundationfunctools — Higher-order functions and operations on callable objectsdocs.python.org
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



