The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Return a closure | return inner | View examples |
| Rebind enclosing state | nonlocal count | View examples |
| Inspect captured values | values = function.__closure__ | View examples |
| Apply a decorator | @decorator | View examples |
| Preserve wrapper metadata | @wraps(function) | View examples |
| Reach the wrapped callable | original = decorated.__wrapped__ | View examples |
| Configure a decorator | @repeat(times=3) | View examples |
| Stack decorators | result = outer(inner(function)) | View examples |
| Make instances callable | def __call__(self, value): return self.prefix + value | View examples |
| Check callability | supported = callable(value) | View examples |
| Bind selected arguments | configured = partial(function, fixed_arg, option=value) | View examples |
| Bind arguments on methods | method = partialmethod(function, fixed_arg) | View examples |
| Register a type implementation | @render.register(str) | View examples |
| Inspect dispatch resolution | implementation = render.dispatch(value_type) | View examples |
| Memoize bounded results | @lru_cache(maxsize=128) | View examples |
| Clear a function cache | function.cache_clear() | View examples |
| Inspect cache statistics | stats = function.cache_info() | View examples |
Python treats functions, bound methods, classes, and objects implementing __call__ as values that can be stored and composed. Closures retain lexical state, decorators replace a definition with a transformed callable, and functools supplies standard adapters. Preserve introspection, make state ownership obvious, and resist wrappers that quietly change the original calling contract.
Step by step
Detailed examples
Capture lexical state deliberately
A closure is a nested function that refers to bindings from an enclosing function after that call has returned. Reading needs no declaration; rebinding requires nonlocal, which targets the nearest enclosing function scope rather than global state. Separate closure instances own separate captured bindings, making closures useful for small configured functions while a class may better express extensive mutable state.
def make_counter(start=0):
count = start
def increment(step=1):
nonlocal count
count += step
return count
return increment
first = make_counter(10)
second = make_counter()
print(first(), first(5))
print(second(), second())
print(first.__closure__[0].cell_contents) 11 16
1 2
16Preserve metadata when wrapping a function
A decorator expression is evaluated when the def statement executes, and its result replaces the defined name. A general wrapper normally accepts *args and **kwargs and returns the original result. functools.wraps copies metadata such as __name__ and __doc__ and exposes __wrapped__, supporting inspection, documentation tools, testing, and further decorator composition.
from functools import wraps
def traced(function):
@wraps(function)
def wrapper(*args, **kwargs):
print(f'calling {function.__name__}')
return function(*args, **kwargs)
return wrapper
@traced
def add(left, right):
"""Add two values."""
return left + right
print(add(2, 3))
print(add.__name__, add.__doc__)
print(add.__wrapped__(4, 5)) calling add
5
add Add two values.
9Configure wrappers with decorator factories
A decorator with arguments adds a factory layer: the expression first produces a decorator, which then receives the function. With stacked decorators, the decorator closest to def is applied first, although calls enter the outermost wrapper first. Validate configuration in the factory so errors appear at definition or import time rather than on a later call.
from functools import wraps
def repeat(times):
if times < 1:
raise ValueError('times must be positive')
def decorate(function):
@wraps(function)
def wrapper(*args, **kwargs):
return [function(*args, **kwargs) for _ in range(times)]
return wrapper
return decorate
@repeat(times=3)
def label(value):
return f'item-{value}'
print(label(7)) ['item-7', 'item-7', 'item-7']Use callable objects when behavior needs explicit state
An instance whose class defines __call__ participates in ordinary call syntax. This keeps configuration and mutable state inspectable as attributes and can be clearer than a deep closure. callable checks whether an object supports calling but cannot prove a particular argument list will succeed; use an explicit protocol or signature inspection when the contract matters.
class Prefixer:
def __init__(self, prefix):
self.prefix = prefix
self.calls = 0
def __call__(self, value):
self.calls += 1
return f'{self.prefix}{value}'
label = Prefixer('ID-')
print(callable(label))
print(label(3), label(8))
print(label.calls) True
ID-3 ID-8
2Pre-bind arguments with partial
functools.partial returns a callable that prepends positional arguments and supplies default keywords while still allowing ordinary call-time arguments. It is useful for adapters passed to APIs expecting a simpler callback. partialmethod provides descriptor-aware binding inside classes. Prefer a named wrapper when the adaptation needs validation, documentation, or nontrivial control flow.
from functools import partial
base2 = partial(int, base=2)
base16 = partial(int, base=16)
print(base2('101101'))
print(base16('ff'))
def label(prefix, value, *, suffix=''):
return f'{prefix}{value}{suffix}'
error = partial(label, 'E-', suffix='!')
print(error(404)) 45
255
E-404!Dispatch on the first argument's type
singledispatch turns a function into a generic function selected from the runtime type of its first argument. Registered implementations follow the class MRO and abstract base class registrations, while the undecorated base function is the fallback. It is an extension mechanism, not multiple dispatch: other argument types do not influence selection.
from functools import singledispatch
@singledispatch
def render(value):
return f'object:{value}'
@render.register
def _(value: list):
return '[' + ','.join(map(str, value)) + ']'
@render.register(str)
def _(value):
return value.upper()
print(render(7))
print(render(['a', 2]))
print(render('ready'))
print(render.dispatch(bool) is render.dispatch(int)) object:7
[a,2]
READY
TrueCache pure, hashable calls with bounded storage
lru_cache stores return values by argument key, so arguments must be hashable and callers with equivalent but differently arranged keyword arguments may occupy separate entries. Caching is appropriate when results depend only on arguments and remain valid. Bound methods include self in the key, and cached references stay alive until eviction or cache_clear, so choose maxsize with memory and freshness in mind.
from functools import lru_cache
@lru_cache(maxsize=2)
def square(value):
print(f'compute {value}')
return value * value
print(square(4))
print(square(4))
print(square.cache_info().hits, square.cache_info().misses)
square.cache_clear()
print(square.cache_info().currsize) compute 4
16
16
1 1
0Local code tester
Compose a stateful decorated callable
Configure a closure, preserve its metadata, and inspect memoization behavior while editing the call sequence.
Press Run to load Python locally.
Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
- Python Software FoundationFunction definitions and decoratorsdocs.python.org
- Python Software Foundationfunctools — Higher-order functions and operations on callable objectsdocs.python.org
- Python Software FoundationNaming and bindingdocs.python.org
- Python Software FoundationPEP 318 – Decorators for Functions and Methodspeps.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.



