before()
Create a wrapper that limits how many times a function can run.
Implementation
Accepts (func, n) or (n, func). The wrapped function will execute the original `func` on the first `n-1` calls; on the nth and subsequent calls, it returns None. Parameters: a : Callable[..., R] or int The function to wrap or the maximum number of invocations. b : int or Callable[..., R] The maximum number of invocations or the function to wrap. Returns: Callable[..., Optional[R]] A wrapper function that will call `func` up to `n-1` times, then return None. Raises: TypeError - If arguments are not provided as (func, int) or (int, func).
Example
def greet(name):
return f"Hello, {name}!"
greeter = before(greet, 3)
greeter("Alice")
Expected output: 'Hello, Alice!'
Alternative usage:
greeter("Bob")
Expected output: 'Hello, Bob!'
Source Code
def before(a: Any, b: Any) -> Callable[..., Optional[R]]:
if callable(a) and isinstance(b, int):
func, times = a, b
elif isinstance(a, int) and callable(b):
times, func = a, b
else:
raise TypeError("before expects (func, int) or (int, func)")
limit = max(times - 1, 0)
calls = [0]
def wrapper(*args: Any, **kwargs: Any) -> Optional[R]:
if calls[0] < limit:
calls[0] += 1
return func(*args, **kwargs) # type: ignore
return None
wrapper.__name__ = func.__name__
wrapper.__doc__ = func.__doc__
wrapper.__wrapped__ = func # type: ignore
return wrapper