Now that you know what decorators can do, let’s actually build one step by step. By the end of this post, you’ll be able to create your own custom decorator from scratch.
Step 1: Define a Simple Function
We start with a normal function that we want to enhance.
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
Step 2: Wrap the Function
Next, we define another function (the wrapper) that adds extra behavior before and after the original function.
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Before the function runs...")
result = func(*args, **kwargs)
print("After the function runs...")
return result
return wrapper
Step 3: Apply the Decorator Manually
We can decorate a function without using @ by reassigning it.
decorated_greet = my_decorator(greet)
decorated_greet("Alice")
Output:
Before the function runs...
Hello, Alice!
After the function runs...
Step 4: Use the @ Syntax
Python gives us a shorthand for applying decorators. Instead of writing decorated_greet = my_decorator(greet),
we just use @my_decorator above the function definition.
@my_decorator
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
Step 5: Keep Original Function Metadata
Without extra care, the decorated function loses its name and docstring.
We fix this using functools.wraps.
from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("Before...")
result = func(*args, **kwargs)
print("After...")
return result
return wrapper
@my_decorator
def greet(name):
"""This function greets a person by name."""
print(f"Hello, {name}!")
print(greet.__name__) # greet
print(greet.__doc__) # This function greets a person by name.
Summary
- A decorator is a function that takes another function and extends its behavior.
- We build it step by step: define → wrap → apply → use
@. - Always use
functools.wrapsto keep the original function’s metadata.
No comments:
Post a Comment