Menu

Sign in to track your progress and unlock all features.

Theme style

Log in

Full lesson preview

Create a Decorator That Limits the Number of Calls

Implement a decorator factory that limits how many times a function can be called and returns a default value thereafter.

Python practice25 minDecorators FundamentalsAdvancedLast updated April 15, 2026

Problem statement

Write a decorator factory limit_calls(max_calls, *, default=None) which returns a decorator. When applied to a function, the resulting wrapped function should only allow up to max_calls successful calls. After the limit is reached, further calls should return the provided default value. The wrapper must expose a .remaining attribute showing how many calls remain, and a .reset() method to restore the remaining count back to max_calls. Requirements: - The decorator factory accepts a non-negative integer max_calls and an optional keyword-only default value (default=None). - Each decorated function maintains its own independent counter. - Use functools.wraps (or equivalent) so wrapped function preserves name and docstring. - The wrapper must provide wrapper.remaining (an integer) and wrapper.reset() to reset the counter. - If max_calls == 0, the wrapped function should return the default on every call until reset is used.

Task

Build a reusable decorator limit_calls(max_calls, *, default=None) that: enforces a call limit, exposes remaining calls, and supports resetting the counter.

Examples

Basic usage

Input

f = limit_calls(2)(lambda x: x + 1); f(3)

Output

4

f is allowed 2 calls. The first call returns 3 + 1 = 4.

Exceeding the limit returns default

Input

(g := limit_calls(1, default='X')(lambda: 'ok'), g(), g())[2]

Output

X

g is allowed 1 successful call (returns 'ok'); the second call returns the default 'X'.

Input format

You will implement the function limit_calls(max_calls, *, default=None). Test inputs create and call decorated functions; each test is a single expression evaluated after your code.

Output format

Each test expression should evaluate to a value (or None). The harness compares str(value) to the expected string.

Constraints

max_calls is a non-negative integer. Do not use external libraries. Use functools.wraps to preserve metadata. The wrapper must expose .remaining (int) and .reset() (callable).

Samples

Sample 1

Input

f = limit_calls(2)(lambda x: x*2); f(5)

Output

10

Two calls allowed; first call returns 5*2 = 10.