nextRound
TechnologiesCoding ProblemsBookmarksLearning PathsLogin
nextRound
TechnologiesCoding ProblemsBookmarksLearning PathsLogin
nextRound

AI-powered interview preparation platform. Practice with curated questions, mock interviews, and personalized learning paths to crack your dream tech interview.

Quick Links

  • Technologies
  • Mock Interviews
  • Saved Questions
  • Pricing

Company

  • About Us
  • Contact Us

Legal

  • Privacy Policy
  • Terms of Use

© 2026 nextRound. All rights reserved.

Questions
7 of 8
1Why is it important to use functools.wraps when writing a decorator?
2What is the difference between a class-based decorator and a function-based decorator?
3How does the yield keyword turn a function into a generator, and what happens to the function's state between calls?
4What is the difference between yield and yield from?
5What is a decorator, and how does it use closures to wrap a function's behavior?
6What is the difference between an iterable and an iterator? What protocol must an object implement to be an iterator?
7How would you write a decorator that accepts arguments (e.g., @retry(times=3))?
8How would you process a very large file that doesn't fit in memory using generators?
PythonPython
Basics
Control Flow and Functions
Data Structures
Comprehensions & Functional Programming
Iterators, Generators & Decorators
Object-Oriented Programming
Exception Handling & Debugging
Concurrency & Parallelism
Performance & Optimization
Testing
Security
Modules, Packaging & Environment
Type Hinting & Modern Python
System Design & Architecture with Python
Best Practices & Design Patterns
Edge Cases & Tricky Interview Questions
07 / 08

How would you write a decorator that accepts arguments (e.g., @retry(times=3))?

Difficulty: 8/10
Decorators, Decorator Factory, Retries, Closures

A decorator factory: outer function takes parameters and returns the real decorator

To accept arguments you add one more level of nesting. The outermost function takes the decorator parameters and returns the actual decorator; that decorator takes the function and returns the wrapper; the wrapper takes the call arguments and contains the behavior. This is why the call site becomes @retry(times=3) with parentheses: retry(times=3) is evaluated first and produces the decorator that Python then applies to the function. Getting the level count right, and validating the parameters in the outermost scope so a bad configuration fails at import time rather than on the first call, is the practical skill here.

  1. 1

    Three levels: parameters -> decorator(fn) -> wrapper(*args, **kwargs). Forget one level and you get either @retry applied to the function or a TypeError at decoration time.

  2. 2

    Validate parameters in the outermost function so misconfiguration fails fast at import, not on the first invocation.

  3. 3

    Retry specifically needs a bounded attempt count, a backoff with jitter, and a narrow exception tuple. Catching bare Exception hides real bugs and makes incident debugging miserable.

  4. 4

    Trade-off: for anything non-trivial, a battle-tested library such as tenacity or backoff gives you jitter, circuit breaking, and async support for free. Hand-rolled retry decorators are a classic source of retry storms.

  5. 5

    Common mistake: writing @retry instead of @retry() and then wondering why the function is never called with the parameters.

  6. 6

    Version note: functools.wraps works the same at any nesting depth. For async targets you need a separate async def wrapper that awaits the coroutine function; a sync wrapper around a coroutine returns an un-awaited coroutine.

javascript

Scenario Questions

0-2 years experience

  1. 1Why does @retry(times=3) need an extra pair of parentheses compared to @retry?
  2. 2What does the outermost function of a parameterized decorator actually return?

2-5 years experience

  1. 1Your retry decorator catches every exception and hides a real bug for weeks. How do you fix the exception handling?
  2. 2You want invalid decorator parameters to fail at import time. Where do you put the validation and why?

5-8 years experience

  1. 1You need retries with exponential backoff, jitter, and a circuit breaker. How do you structure this without a giant nested decorator?
  2. 2You need identical retry semantics for async functions. What changes in the wrapper, and what breaks if you forget?

8+ years experience

  1. 1Design a retry policy layer shared across many services that is idempotency-aware and emits observability data per attempt.
  2. 2Your parameterized decorator must stay introspectable and type-check cleanly under mypy. How do you annotate the factory and the wrapper?

Follow-up Questions

  • Why does @retry require parentheses while @retry(times=3) does not look like a decorator at all?
  • How would you add async support to this retry decorator without duplicating the logic?
Sharethis question

Share via WhatsApp, X, Facebook, LinkedIn or copy link. Open Graph preview enabled.