Introduction
Decorators will confuse most students at some point. It is one line above a function and all of a sudden, the function prints out logs that were not written by you. It is like magic, but decorators obey very clear and understandable rules which can be learned within an hour. Many students encounter decorators within a well-structured Python Online Course, but this concept becomes easier to understand with a small example.
This article will guide you through the whole process of execution, beginning with the source function and ending with the function call itself. By the end, you'll know exactly how to change the behaviour without changing the source code. There is no need to dig deep into theory, only practical examples are provided that work on any computer.
What Are Python Decorators and Why Do Developers Use Them?
A decorator is an object that takes other objects as parameters and returns an object. It means you do gift wrapping. The gift itself won’t change, but the wrapper will.
Decorators make it possible to introduce some common behaviour for several functions without changing the function code itself.
Use case | What it adds. |
Logging | Records every call |
Timing | Measures how long a call takes |
Access checks | Blocks unauthorized users |
Caching | Stores results for repeated calls |
It is coded only once but works universally, which makes the code look pretty nice.
The Process: How Python Decorators Change a Function’s Work Without Modifying It
Here are the steps required to implement this trick in six points with just a simple example.
Step 1: Create a function that does not do anything except do one thing, like saying hi to someone.
Step 2: Write a decorator for that function by putting it into another function.
Step 3: In the wrapper, add behaviour before or after calling the original function.
Step 4: Return the wrapper, not its output, so that the extra behaviour surrounds the execution of the original function.
Step 5: Add @log_call above the function, which is merely shorthand for greet = log_call(greet).
Step 6: Invoke greet() as usual. Python executes the wrapper, adding behaviour and invoking the original.
Here is the result of calling greet("Asha") before and after decoration:
Without decorator | With decorator |
Hello, Asha! | Calling greet... then Done. then Hello, Asha! |
It does so because functions are objects that can be used as parameters for other functions and even returned by them. The function greet has not been changed at all except for the fact that it now points to the wrapper that is returned by the decorator.
What Happens When Python Executes a Decorator?
The decorator is run by Python only once, at the time of definition of the function. From here onward, the name greet will point to the wrapper, while the original function will be inside it.
Item | Before decoration | After decoration |
Name greet | Original function | Wrapper |
Original function | Called directly | Called by the wrapper |
__name__ | greet | wrapper (unless fixed) |
That final line of code creates quite a mess since debugging tools will start displaying the wrapper's name instead of the original one. The way out is to use functools.wraps, which is a helper function that will copy the name and the docstring of the original function to the wrapper.
How Can Decorators Add Different Behaviours to the Same Function?
A single function can have many different capabilities depending on the decorator used.
@log_call will output a message every time the function is called.
@timer will measure the time taken for the call, useful in identifying slow functions.
@login_required will first verify permissions before executing the function.
@cache will cache the output, so any further calls with the same parameters will execute instantly.
More than one decorator can be used on the same function, but the order is crucial.
In this case, log_call will decorate the greet function first, followed by timer decorating the outcome, which means that timer is going to be executed last for each invocation.
What Should Developers Check When Writing Python Decorators?
The best decorators are concise; however, there are a few things programmers can do to ensure they are secure enough for real-life projects. Students taking a Python Classes in Delhi usually start learning these testing skills on small projects.
Check | Why it matters |
Use *args and **kwargs | The wrapper accepts any arguments |
Return the result | Callers still get the original value |
Apply functools.wraps | Name and docstring stay intact |
Handle exceptions | Errors should not vanish silently |
Watch execution order | Stacked decorators run in layers |
Remember that when it comes to decorators, we are changing some behaviour, which means that before releasing something, make sure you have tested return values and exceptions.
Conclusion
In any case, the decorator doesn’t really change a function; it just assigns a more sophisticated function to its name. Once you have grasped this idea, logging, timing, caching, and access control all become different instances of the same technique. Try applying the six steps to simple functions to get used to wrapping them. Start from the smallest example, break something deliberately, and observe the result each time.