What is decorator?
A decorator is a special kind of function that takes another function (or method) as input, adds some extra behavior to it, and then returns a new function with that added behavior. In simple terms, it “wraps” the original code so you can run extra code before or after the original function runs, without changing the original function’s code.
Let's break it down
- Original function - the piece of code you want to enhance (e.g., a function that calculates a total).
- Wrapper function - a new function created inside the decorator that calls the original function and adds extra steps (like printing a message, checking permissions, or measuring time).
- Decorator function - the outer function that receives the original function, builds the wrapper, and returns it.
- @ syntax - a shortcut in languages like Python that lets you apply a decorator to a function by writing
@my_decorator
just above the function definition.
Why does it matter?
Decorators let you keep your code clean and DRY (Don’t Repeat Yourself). Instead of copying the same pre‑ or post‑processing code into many functions, you write it once in a decorator and apply it wherever needed. This makes it easier to add features like logging, authentication, caching, or timing without cluttering the core logic of your functions.
Where is it used?
- Python - built‑in decorators like
@staticmethod
,@property
, and user‑defined ones for logging, retries, etc. - JavaScript - experimental decorator syntax for classes and methods, often used in frameworks like Angular or TypeScript.
- Web frameworks - Flask and Django use decorators to define routes (
@app.route('/')
) or require login (@login_required
). - Testing - pytest uses decorators to mark test functions (
@pytest.mark.parametrize
).
Good things about it
- Promotes code reuse and separation of concerns.
- Keeps the main function focused on its primary task.
- Easy to read when using the
@
syntax; the intent is clear at a glance. - Can be stacked, allowing multiple independent enhancements on the same function.
Not-so-good things
- Can make debugging harder because the original function is wrapped inside another layer.
- Overuse may lead to “decorator hell,” where many stacked decorators become confusing.
- Some languages only support decorators experimentally, so portability can be an issue.
- If not written carefully, decorators can unintentionally change a function’s signature or behavior, leading to subtle bugs.