⬅ Previous Topic
Python ClosuresNext Topic ⮕
Python Email Tutorial⬅ Previous Topic
Python ClosuresNext Topic ⮕
Python Email TutorialDecorators in Python are a powerful tool that allows you to modify the behavior of functions or classes. If you're coming from a beginner’s perspective, think of a decorator as a "wrapper" that adds extra features to an existing function without changing its core code.
Imagine you want to log the execution time of various functions or check user authentication before executing a task. You could repeat that logic inside every function... or, you could just use a decorator. It keeps your code clean, modular, and reusable.
Before diving into decorators, it’s important to know that in Python, functions are first-class objects. This means:
def greet():
return "Hello!"
say_hello = greet
print(say_hello())
Hello!
A decorator is simply a function that takes another function as input and returns a new function with added behavior.
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
def say_hi():
print("Hi!")
decorated = my_decorator(say_hi)
decorated()
Something is happening before the function is called.
Hi!
Something is happening after the function is called.
@
Syntax (Syntactic Sugar)Python provides a cleaner way to apply decorators using the @
symbol.
@my_decorator
def say_hi():
print("Hi!")
say_hi()
Something is happening before the function is called.
Hi!
Something is happening after the function is called.
If your target function has parameters, your wrapper needs to accept them too.
def log_args(func):
def wrapper(*args, **kwargs):
print(f"Arguments passed: {args}, {kwargs}")
return func(*args, **kwargs)
return wrapper
@log_args
def add(x, y):
return x + y
print(add(5, 7))
Arguments passed: (5, 7), {}
12
Always remember to return the result of the original function if it produces one.
functools.wraps
When you use decorators, the metadata of the original function (like its name or docstring) can get lost. To preserve it, use functools.wraps
.
import functools
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print("Before function call")
result = func(*args, **kwargs)
print("After function call")
return result
return wrapper
@my_decorator
def greet(name):
"Greets a user by name"
print(f"Hello, {name}")
print(greet.__name__)
print(greet.__doc__)
Before function call
Hello, Alice
After function call
greet
Greets a user by name
Python includes several built-in decorators:
@staticmethod
@classmethod
@property
class MyClass:
@staticmethod
def static_method():
print("This is a static method.")
@classmethod
def class_method(cls):
print(f"This is a class method from {cls.__name__}")
@property
def name(self):
return "TutorialKart"
obj = MyClass()
obj.static_method()
obj.class_method()
print(obj.name)
This is a static method.
This is a class method from MyClass
TutorialKart
functools.wraps
when writing decorators.To ensure your decorator works as expected:
__name__
and __doc__
.Decorators are one of Python’s elegant ways to inject functionality without altering existing code. Whether you’re logging, validating, or checking permissions — they let you write cleaner, modular code that feels both powerful and Pythonic. Now that you've mastered the basics, go ahead and create your own decorators to supercharge your functions!
⬅ Previous Topic
Python ClosuresNext Topic ⮕
Python Email TutorialYou can support this website with a contribution of your choice.
When making a contribution, mention your name, and programguru.org in the message. Your name shall be displayed in the sponsors list.