Menu

Sign in to track your progress and unlock all features.

Theme style

Log in

Full lesson preview

Implement a Decorator That Counts Successful Calls

Create a decorator that wraps a function and counts how many times it completed successfully (returned a truthy value without raising). Attach the count to the wrapper.

Python practice15 minDecorators FundamentalsIntermediateLast updated April 15, 2026

Problem statement

Write a decorator count_successful that wraps any callable and tracks the number of times the wrapped function completes without raising an exception and returns a truthy value. The decorator must: - Work with functions that accept any positional and keyword arguments. - Preserve the wrapped function's metadata (__name__, __doc__) using functools.wraps. - Expose the counter as an integer attribute successful_calls on the wrapper function (initialized to 0). - Increment successful_calls only when the call completes (no exception) and the return value is truthy (bool(result) is True). - If the wrapped function raises an exception, the decorator should NOT increment the counter and must re-raise the same exception. You must implement only the decorator function; the tests will exercise decorated functions that demonstrate counting behavior.

Task

Implement a Python decorator count_successful that increments an accessible counter only when the wrapped function returns a truthy value and does not raise; preserve metadata with functools.wraps.

Examples

Basic usage

Input

@count_successful def is_positive(n): return n > 0 is_positive(3) is_positive(0) print(is_positive.successful_calls)

Output

1

is_positive(3) returns True (counts), is_positive(0) returns False (does not count). The successful_calls attribute should be 1.

Input format

The submission must implement the decorator count_successful. Tests will call decorated functions and inspect the successful_calls attribute.

Output format

Each test evaluates an expression; returned values (or tuples) are compared as str(...) to the expected outputs.

Constraints

Do not use global variables to track counts. Use functools.wraps to preserve metadata. The decorator must work for any callable signature.

Samples

Sample 1

Input

@count_successful def collect_if_positive(n): return [n] if n > 0 else [] collect_if_positive(0) collect_if_positive(5) collect_if_positive.successful_calls

Output

1

collect_if_positive(0) returns [], which is falsy and should not be counted. collect_if_positive(5) returns [5], which is truthy and should be counted once.