β¨ Python Function Decorators β Add Superpowers to Your Functions
Introduction π
A decorator in Python is a function that wraps another function to **add extra behavior** without modifying the original functionβs code. Decorators use the @ syntax and are widely used in logging, authentication, performance tracking, and more.
Note
π‘ Decorators follow a powerful concept: functions can be passed as arguments and returned as values.
1. Basic Decorator Structure π§±
basic_decorator.py
def my_decorator(func):
def wrapper():
print("Before function call")
func()
print("After function call")
return wrapper
@my_decorator
def greet():
print("Hello!")
greet()β The decorator adds code before and after the original function.
2. How Decorators Work Internally π
decorator_internal.py
def my_decorator(func):
def wrapper():
print("Before")
func()
print("After")
return wrapper
def greet():
print("Hello")
greet = my_decorator(greet) # Manual decoration
greet()Note
β @decorator is just syntactic sugar for manual decoration.
3. Decorator with Arguments π€
decorator_args.py
def smart_divide(func):
def wrapper(a, b):
print("Dividing", a, "and", b)
if b == 0:
return "Error: Cannot divide by zero!"
return func(a, b)
return wrapper
@smart_divide
def divide(a, b):
return a / b
print(divide(10, 2))
print(divide(10, 0))4. Decorators Using *args and **kwargs π―
To handle any number of arguments, always use:
args_kwargs_decorator.py
def logger(func):
def wrapper(*args, **kwargs):
print("Arguments:", args, kwargs)
return func(*args, **kwargs)
return wrapper
@logger
def add(a, b):
return a + b
print(add(10, 20))5. Decorator that Returns a Value π
decorator_return_value.py
def uppercase(func):
def wrapper():
result = func()
return result.upper()
return wrapper
@uppercase
def message():
return "hello world"
print(message())6. Chaining Multiple Decorators βοΈ
multiple_decorators.py
def bold(func):
def wrapper():
return "<b>" + func() + "</b>"
return wrapper
def italic(func):
def wrapper():
return "<i>" + func() + "</i>"
return wrapper
@bold
@italic
def text():
return "Hello"
print(text()) # <b><i>Hello</i></b>Note
β Decorators run from bottom to top.
7. Using Decorators for Logging π
decorator_logging.py
def log(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper
@log
def greet(name):
print("Hello", name)
greet("Sathish")8. Timing a Function β±οΈ
decorator_timer.py
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print("Time taken:", end - start)
return result
return wrapper
@timer
def slow():
time.sleep(2)
slow()9. Authentication Decorator π
decorator_auth.py
def require_login(func):
def wrapper(user):
if user != "admin":
return "Access Denied"
return func(user)
return wrapper
@require_login
def dashboard(user):
return f"Welcome {user}"
print(dashboard("guest"))
print(dashboard("admin"))10. Using functools.wraps π
Without wraps, the wrapper function hides the original function's name and docstring.
wraps_example.py
from functools import wraps
def log(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("Called", func.__name__)
return func(*args, **kwargs)
return wrapper
@log
def greet():
"""This is the greeting function."""
print("Hello")
print(greet.__name__) # greet
print(greet.__doc__) # This is the greeting function.Note
β Always use @wraps inside decorators.
11. Decorator That Accepts Parameters ποΈ
decorator_with_params.py
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def hello():
print("Hello!")
hello()β Decorator takes an argument β returns another decorator.
12. Real-World Use Cases π
Logging API Requests
api_logging.py
@log
def fetch_data(url):
return "Data from " + url
fetch_data("https://example.com")Restricting Access
role_based.py
def roles_allowed(role):
def decorator(func):
def wrapper(user_role):
if user_role != role:
return "Permission denied"
return func(user_role)
return wrapper
return decorator
@roles_allowed("admin")
def delete_record(role):
return "Record deleted"
print(delete_record("user"))
print(delete_record("admin"))Memoization (Caching) π
memoization.py
def cache(func):
memory = {}
def wrapper(n):
if n in memory:
return memory[n]
result = func(n)
memory[n] = result
return result
return wrapper
@cache
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
print(fib(30))Conclusion π
>>βDecorators wrap functions with extra power β clean, elegant, and extremely useful.β β¨
You now fully understand Function Decorators in Python! Want the next topic? Try Modules, Classes & Objects (OOP), Error Handling, or Decorators with Classes. Just tell me! π