Python Advance Course
Decorators in Python (Advanced)
Decorators in Python (Advanced)
A decorator is a function that modifies another function without changing its actual code.
Decorators are built using: - Functions - Closures - Higher-order functions
Basic Idea of Decorators
A decorator: - Takes a function as input - Adds extra behavior - Returns a new function
1. Function Decorators
Basic decorator example:
def decorator(func):
def wrapper():
print("Before function runs")
func()
print("After function runs")
return wrapper
def say_hello():
print("Hello")
decorated = decorator(say_hello)
decorated()
Output:
Before function runs
Hello
After function runs
Using @ syntax (Pythonic way)
def decorator(func):
def wrapper():
print("Before")
func()
print("After")
return wrapper
@decorator
def greet():
print("Good Morning")
greet()
Real World Example
| Scenario | Decorator Use |
|---|---|
| Login check | authentication |
| Logging | request logs |
| Timing | performance check |
Graph (Flow)
greet()
|
v
wrapper()
|
+--> Before logic
+--> Original function
+--> After logic
Common Mistake
@decorator()
def func():
print("Hi")
Error: - Missing function reference
Correct:
@decorator
Homework 1
Create a decorator that prints: - "Start" - "End"
Solution:
def decorator(func):
def wrapper():
print("Start")
func()
print("End")
return wrapper
@decorator
def hello():
print("Hello World")
hello()
2. Decorator Chaining
Multiple decorators can be applied to one function.
Example:
def deco1(func):
def wrapper():
print("Decorator 1")
func()
return wrapper
def deco2(func):
def wrapper():
print("Decorator 2")
func()
return wrapper
@deco1
@deco2
def show():
print("Original Function")
show()
Output:
Decorator 1
Decorator 2
Original Function
Execution Flow
@deco1
↓
@deco2
↓
function()
Real World Example
| Layer | Use |
|---|---|
| Authentication | login check |
| Authorization | permission check |
| Logging | request logs |
Homework 2
Create two decorators: - One prints "A" - Another prints "B"
Apply both to a function.
3. Decorators with Arguments
Sometimes decorators need parameters.
Example:
def repeat(n):
def decorator(func):
def wrapper():
for i in range(n):
func()
return wrapper
return decorator
@repeat(3)
def hello():
print("Hello")
hello()
Output:
Hello
Hello
Hello
Real World Example
| Use Case | Example |
|---|---|
| Retry system | retry 3 times |
| Logging level | debug/info |
| Rate limiting | 5 requests |
Graph
repeat(n)
↓
decorator(func)
↓
wrapper()
↓
loop execution
Common Mistake
@repeat
def func():
print("Hi")
Problem: - Missing argument
Correct:
@repeat(3)
Homework 3
Create a decorator that repeats function 5 times.
4. functools.wraps
When using decorators, function metadata is lost.
Example problem:
def decorator(func):
def wrapper():
return func()
return wrapper
@decorator
def hello():
"This is hello function"
print("Hello")
print(hello.__name__)
Output:
wrapper
Fix using wraps
from functools import wraps
def decorator(func):
@wraps(func)
def wrapper():
return func()
return wrapper
@decorator
def hello():
print("Hello")
print(hello.__name__)
Output:
hello
Why wraps is important
| Without wraps | With wraps |
|---|---|
| wrapper name shown | original name preserved |
| loses docstring | keeps metadata |
Homework 4
Apply wraps in a decorator and check function name.
5. Real-World Decorators
Logging Decorator
def log(func):
def wrapper(*args, **kwargs):
print("Function is running")
return func(*args, **kwargs)
return wrapper
@log
def add(a, b):
return a + b
print(add(5, 3))
Output:
Function is running
8
Authentication Decorator
def login_required(func):
def wrapper(user):
if user == "admin":
return func(user)
return "Access Denied"
return wrapper
@login_required
def dashboard(user):
return "Welcome Admin"
print(dashboard("admin"))
Timing Decorator
import time
def timer(func):
def wrapper():
start = time.time()
func()
end = time.time()
print("Time:", end - start)
return wrapper
Real World Mapping
| Decorator | Use Case |
|---|---|
| logging | system logs |
| auth | login check |
| timer | performance monitoring |
| retry | API retry logic |
Summary Table
| Concept | Meaning |
|---|---|
| Decorator | modifies function behavior |
| Chaining | multiple decorators |
| Arguments | parameterized decorators |
| wraps | preserves metadata |
Decorator Flow Diagram
function
↓
decorator(func)
↓
wrapper()
↓
modified behavior
Homework 5 (Final Challenge)
Create a decorator that: - logs function name - logs arguments - logs result
Solution
def logger(func):
def wrapper(*args, **kwargs):
print("Function:", func.__name__)
print("Args:", args)
result = func(*args, **kwargs)
print("Result:", result)
return result
return wrapper
@logger
def multiply(a, b):
return a * b
multiply(4, 5)
Next Advanced Topics
- Generators
- Iterators
- Context Managers
- Async Programming (async/await)
- functools (partial, reduce, lru_cache)
- Metaclasses ```