Skip to main content

Lib/functools.py

cpython 3.14 @ ab2d84fe1023/Lib/functools.py

The pure-Python complement to Modules/_functoolsmodule.c. It imports and re-exports the accelerated implementations of reduce, partial, Placeholder, _lru_cache_wrapper, and cmp_to_key from the C extension when available, and provides Python fallbacks for the rest. Everything in __all__ is public: update_wrapper, wraps, WRAPPER_ASSIGNMENTS, WRAPPER_UPDATES, total_ordering, cache, cmp_to_key, lru_cache, reduce, partial, partialmethod, singledispatch, singledispatchmethod, cached_property, and Placeholder.

In CPython 3.14, WRAPPER_ASSIGNMENTS gained __annotate__ and __type_params__ (PEP 649 deferred annotations). singledispatch switched from __annotations__ to annotationlib.Format.FORWARDREF for annotation-driven registration.

Map

LinesSymbolRolegopy
32-77WRAPPER_ASSIGNMENTS, update_wrapper, wrapsCopy name/doc/dict from wrapped to wrapper; the wraps decorator is partial(update_wrapper, ...).stdlib/functools.py
89-199_gt_from_lt_convert, total_orderingTwelve fill-in comparison helpers and the class decorator that injects them.stdlib/functools.py
206-228cmp_to_keyWraps a two-argument comparator into a key object; C override at line 225.stdlib/functools.py
273-440_PlaceholderType, Placeholder, partialPartial application with positional placeholder support; C override at line 437.stdlib/functools.py
443-514partialmethodDescriptor variant of partial for use inside class bodies.stdlib/functools.py
520-728_make_key, lru_cache, _lru_cache_wrapper, cacheLRU cache and its unbounded alias; Python implementation used when C extension missing.stdlib/functools.py
735-991_c3_merge, _c3_mro, _compose_mro, _find_impl, singledispatchSingle-dispatch infrastructure: C3 MRO computation, ABC-aware dispatch table, and the decorator itself.stdlib/functools.py
994-1086singledispatchmethod, _singledispatchmethod_getDescriptor version of singledispatch for methods; __get__ returns a bound helper.stdlib/functools.py
1094-1137cached_propertyNon-data descriptor that computes on first access and stores the result in the instance __dict__.stdlib/functools.py

Reading

total_ordering (lines 89 to 199)

cpython 3.14 @ ab2d84fe1023/Lib/functools.py#L89-199

_convert = {
'__lt__': [('__gt__', _gt_from_lt),
('__le__', _le_from_lt),
('__ge__', _ge_from_lt)],
...
}

def total_ordering(cls):
roots = {op for op in _convert
if getattr(cls, op, None) is not getattr(object, op, None)}
if not roots:
raise ValueError('must define at least one ordering operation: < > <= >=')
root = max(roots) # prefer __lt__ to __le__ to __gt__ to __ge__
for opname, opfunc in _convert[root]:
if opname not in roots:
opfunc.__name__ = opname
setattr(cls, opname, opfunc)
return cls

The decorator scans the class for user-defined comparison methods (those not equal to object's default implementation). It picks one as the root by string comparison, which gives the documented priority __lt__ > __le__ > __gt__ > __ge__. For each missing method it injects one of the twelve private helpers (_gt_from_lt, _le_from_lt, etc.) that call type(self).__root__(self, other) directly to avoid infinite recursion through the operator dispatch fallback path.

singledispatch dispatch table and MRO walk (lines 735 to 991)

cpython 3.14 @ ab2d84fe1023/Lib/functools.py#L735-991

def singledispatch(func):
registry = {}
dispatch_cache = weakref.WeakKeyDictionary()
cache_token = None

def dispatch(cls):
nonlocal cache_token
if cache_token is not None:
current_token = get_cache_token()
if cache_token != current_token:
dispatch_cache.clear()
cache_token = current_token
try:
impl = dispatch_cache[cls]
except KeyError:
try:
impl = registry[cls]
except KeyError:
impl = _find_impl(cls, registry)
dispatch_cache[cls] = impl
return impl

registry maps types to callables. The fast path checks dispatch_cache (a WeakKeyDictionary keyed by type) before falling back to _find_impl. _find_impl calls _compose_mro to build an extended MRO that inserts registered ABCs at the right positions, then walks the MRO until it finds a matching entry. Results are cached in dispatch_cache and invalidated whenever get_cache_token() changes (i.e., whenever an ABC registers a new virtual subclass). register also accepts Union-typed annotations via annotationlib.Format.FORWARDREF in 3.14, replacing the old __annotations__ dict look-up.

cached_property (lines 1094 to 1137)

cpython 3.14 @ ab2d84fe1023/Lib/functools.py#L1094-1137

class cached_property:
def __get__(self, instance, owner=None):
if instance is None:
return self
if self.attrname is None:
raise TypeError(
"Cannot use cached_property instance without calling __set_name__ on it.")
cache = instance.__dict__
val = cache.get(self.attrname, _NOT_FOUND)
if val is _NOT_FOUND:
val = self.func(instance)
cache[self.attrname] = val
return val

cached_property is a non-data descriptor (no __set__), so the instance __dict__ lookup takes precedence over the descriptor on all subsequent accesses. __set_name__ records the attribute name; if the property is used without it (e.g., constructed and assigned manually) __get__ raises a TypeError. Objects without __dict__ (e.g., those with __slots__) also raise TypeError with a diagnostic message.