mediumBackend EngineerFintech
Explain Python decorators — how do they work, and when would you write a custom decorator?
Posted 18/04/2026
by Mehedy Hasan Ador
Question Details
At a fintech company:
> "We need to add timing, logging, and access control to our API handlers without modifying each function. Can you implement decorators for these use cases?"
> "We need to add timing, logging, and access control to our API handlers without modifying each function. Can you implement decorators for these use cases?"
Suggested Solution
What Are Decorators?
Decorators are higher-order functions that wrap another function to extend its behavior.def timer(func):
import time
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - start
print(f"{func._name} took {elapsed:.3f}s")
return result
return wrapper
@timer
def fetchdata(query):
# ... slow operation
return results
Equivalent to: fetchdata = timer(fetchdata)
Decorators with Arguments
def requirerole(role):
def decorator(func):
def wrapper(user, *args, **kwargs):
if user.role != role:
raise PermissionError(f"Requires {role}")
return func(user, *args, **kwargs)
return wrapper
return decorator
@requirerole("admin")
def deleteuser(user, userid):
db.delete(userid)
Class-Based Decorator (stateful)
class RateLimit:
def init(self, maxcalls, period):
self.maxcalls = maxcalls
self.period = period
self.calls = []
def _call(self, func):
def wrapper(*args, **kwargs):
now = time.time()
self.calls = [t for t in self.calls if now - t < self.period]
if len(self.calls) >= self.maxcalls:
raise Exception("Rate limit exceeded")
self.calls.append(now)
return func(*args, **kwargs)
return wrapper
@RateLimit(maxcalls=100, period=60)
def apiendpoint():
return {"status": "ok"}
functools.wraps (preserve metadata)
from functools import wraps
def logged(func):
@wraps(func) # Preserves _name, doc, etc.
def wrapper(*args, **kwargs):
print(f"Calling {func.name_}")
return func(*args, **kwargs)
return wrapper
@wraps