Menu

Sign in to track your progress and unlock all features.

Theme style

Log in

Full lesson preview

Build a Decorator That Memoizes Pure Functions

Implement a memoization decorator that caches results of pure functions with hashable arguments and preserves function metadata.

Python practice25 minDecorators FundamentalsAdvancedLast updated April 15, 2026

Problem statement

Memoization (caching of function results) is a powerful technique to avoid recomputing expensive pure function calls when inputs repeat. Build a Python decorator named memoize that: - Caches results per-call based on the function's positional and keyword arguments. - Uses a tuple of args and a deterministic representation of kwargs as the cache key (e.g., tuple(sorted(kwargs.items()))). - Preserves the wrapped function's metadata using functools.wraps. - If any part of the key is unhashable (for example, lists inside args), the decorator should not raise an error; instead it should call the original function without caching and return its result. Your decorator must work for ordinary functions (including recursive ones like a memoized fibonacci). Keep the implementation simple and self-contained; thread-safety is not required for this exercise.

Task

Write a decorator @memoize that caches call results for functions called with hashable positional and keyword arguments, while safely handling unhashable arguments by bypassing the cache.

Examples

Basic caching

Input

add(1, 2, scale=3)

Output

9

add(1,2,scale=3) returns (1+2)*3 = 9 and the result will be cached for later calls with the same arguments.

Input format

A single function call expression that will be evaluated in the test harness, e.g. fib(10) or add(1, 2, scale=3).

Output format

The function result (the test harness compares str(return_value) to the expected string).

Constraints

Cache only when a deterministic, hashable key can be built from (args, kwargs). Do not attempt to serialize arbitrary objects. If construction of the key raises TypeError (unhashable component), call the original function directly without caching. Use functools.wraps to preserve metadata.

Samples

Sample 1

Input

fib(6)

Output

8

With memoization, recursive fib(6) should compute quickly and return 8.