CodeBlanks Logo Icon CodeBlanks

Summary - Advanced decorators

Combine lru_cache, partial and class decorator to write a cache layer.

Summary - Advanced decorators

This group covered advanced decorators. A parameterized decorator has three layers: factory → decorator → wrapper. A class decorator holds state through __call__.

The functools module gave us three tools: wraps preserves metadata, lru_cache caches results, partial binds arguments, and reduce folds a sequence into one value.

The final task combines a parameterized decorator with lru_cache: repeat count and caching side by side.

Practice Combine repeat and lru_cache

Write the parameterized repeat(n) decorator (factory, deco, wrapper; with @wraps(fn)). wrapper calls fn(*args) n times and returns the last result. Decorate slow_square(n) with @lru_cache(maxsize=None) and @repeat(3) (lru_cache on top). Print the result of slow_square(4).

Starter code

main.py
from functools import wraps, lru_cache

# repeat(n): factory → deco → wrapper; call n times, return result
# decorate wrapper with the wraps decorator
# also decorate slow_square with lru_cache(maxsize=None) on top
# finally print the result of slow_square(4)

@repeat(3)
def slow_square(n):
    return n * n

Sample solution

main.py
from functools import wraps, lru_cache

def repeat(n):
    def deco(fn):
        @wraps(fn)
        def wrapper(*args):
            result = None
            for _ in range(n):
                result = fn(*args)
            return result
        return wrapper
    return deco

@lru_cache(maxsize=None)
@repeat(3)
def slow_square(n):
    return n * n

print(slow_square(4))

Expected output

16

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 In what order does the combined decorator chain run?

  • lru_cache first, then repeat
  • repeat first, then lru_cache Correct answer
  • In parallel at the same time
  • Only repeat; lru_cache is ignored

Explanation: @repeat(3) is applied first; each call then caches the wrapped function's result via lru_cache.

2 Combine the decorator with lru_cache

Question
from functools import wraps, lru_cache

@____(maxsize=None)
@repeat(3)
def slow_square(n):
    return n * n
Answer
from functools import wraps, lru_cache

@lru_cache(maxsize=None)
@repeat(3)
def slow_square(n):
    return n * n

Explanation: @lru_cache(maxsize=None) is on top; repeat(3) below is applied first.

3 Match the group concepts

Term Meaning
repeat(n) Parameterized factory
class Counter Holds state
lru_cache Result cache
partial Binds arguments

All lessons in Advanced