Python Decorators and a Retry Decorator That Re-Runs a Function Until It Succeeds

Read the full interview experience this question came from →

Quick Overview

Explain what a Python decorator is and how the @ syntax works, then write a try/retry decorator that re-runs any function until it succeeds. It tests closures, functools.wraps, decorators with arguments, exception filtering, backoff and safe retry limits.

Python Decorators and a Retry Decorator That Re-Runs a Function Until It Succeeds

Company: Raiffeisenbank

Role: Machine Learning Engineer

Category: Software Engineering Fundamentals

Difficulty: hard

Interview Round: Technical Screen

Explain what a decorator is in Python. Then write a try/retry decorator that repeatedly executes any function until it completes successfully. ### Clarifying Questions - Should retries be unlimited, as stated, or capped by a maximum number of attempts or a total time? - Which exceptions should trigger a retry, and which should propagate immediately? - Should there be a delay between attempts, and should it grow after each failure? - Must the decorator work both as `@retry` and as `@retry(...)` with arguments, and with `async` functions? ### Part 1 — What a decorator is Explain what a decorator is and how the `@` syntax works, and give a short example. ```hint Functions are objects Write out what `@name` above a `def` is equivalent to, without using the `@`. ``` #### What This Part Should Cover - The mechanics: a callable that takes a function and returns a replacement, applied when the function is defined - Closures, `*args` and `**kwargs`, and `functools.wraps` - Decorators with arguments, stacking order, and common built-in decorators ### Part 2 — A retry decorator Write a decorator that re-executes the decorated function until it completes without raising, then returns its result. It must work for functions with any signature. ```hint Loop inside the wrapper The retry loop belongs inside the function that replaces the original. Decide what happens to the exception after each failed attempt. ``` #### What This Part Should Cover - A correct wrapper that passes arguments through, returns the result and keeps the function's metadata - A retry policy: which exceptions retry, limits, backoff, and re-raising the last error - When retrying is unsafe, and how to test the decorator ### What a Strong Answer Covers - A precise explanation of decorators as higher-order functions applied at definition time - Correct use of closures, `*args` and `**kwargs`, and `functools.wraps` - A working retry decorator, usable with and without arguments - A sound retry policy: exception filtering, attempt or time limits, exponential backoff with jitter, re-raising the final error - Awareness of when retrying is dangerous, such as non-idempotent operations ### Follow-up Questions - How would you make the same decorator work for `async def` functions? - Why should a retry decorator not catch `KeyboardInterrupt`, and what changes between catching `Exception` and `BaseException`? - How would you unit-test the decorator without actually sleeping? - When is retrying an operation dangerous?

Overview: Explain what a Python decorator is and how the @ syntax works, then write a try/retry decorator that re-runs any function until it succeeds. It tests closures, functools.wraps, decorators with arguments, exception filtering, backoff and safe retry limits.

Read the full Raiffeisenbank Machine Learning Engineer interview experience this question came from

Raiffeisenbank logo
Raiffeisenbank
Apr 15, 2026
hardMachine Learning EngineerTechnical ScreenSoftware Engineering Fundamentals
0
0

Explain what a decorator is in Python. Then write a try/retry decorator that repeatedly executes any function until it completes successfully.

Clarifying Questions Guidance

  • Should retries be unlimited, as stated, or capped by a maximum number of attempts or a total time?
  • Which exceptions should trigger a retry, and which should propagate immediately?
  • Should there be a delay between attempts, and should it grow after each failure?
  • Must the decorator work both as @retry and as @retry(...) with arguments, and with async functions?

Part 1 — What a decorator is

Explain what a decorator is and how the @ syntax works, and give a short example.

What This Part Should Cover Guidance

  • The mechanics: a callable that takes a function and returns a replacement, applied when the function is defined
  • Closures, *args and **kwargs , and functools.wraps
  • Decorators with arguments, stacking order, and common built-in decorators

Part 2 — A retry decorator

Write a decorator that re-executes the decorated function until it completes without raising, then returns its result. It must work for functions with any signature.

What This Part Should Cover Guidance

  • A correct wrapper that passes arguments through, returns the result and keeps the function's metadata
  • A retry policy: which exceptions retry, limits, backoff, and re-raising the last error
  • When retrying is unsafe, and how to test the decorator

What a Strong Answer Covers Guidance

  • A precise explanation of decorators as higher-order functions applied at definition time
  • Correct use of closures, *args and **kwargs , and functools.wraps
  • A working retry decorator, usable with and without arguments
  • A sound retry policy: exception filtering, attempt or time limits, exponential backoff with jitter, re-raising the final error
  • Awareness of when retrying is dangerous, such as non-idempotent operations

Follow-up Questions Guidance

  • How would you make the same decorator work for async def functions?
  • Why should a retry decorator not catch KeyboardInterrupt , and what changes between catching Exception and BaseException ?
  • How would you unit-test the decorator without actually sleeping?
  • When is retrying an operation dangerous?