Decorator – Gói thêm chức năng cho hàm
Decorator là một khái niệm cực kỳ mạnh mẽ và phổ biến trong Python – đặc biệt khi bạn muốn gói thêm (wrap) chức năng cho một hàm mà không thay đổi mã gốc.
Decorator là một hàm dùng để gói thêm logic cho một hàm khác.
Bạn có thể hình dung nó giống như việc “bọc thêm lớp áo” cho một người – người đó vẫn là người đó, nhưng có thêm tính năng mới (ví dụ: áo giáp, áo tàng hình,... ).
I. Cấu trúc cơ bản
def my_decorator(func):
def wrapper(*args, **kwargs):
# Thêm chức năng trước khi gọi func
print("Bắt đầu gọi hàm...")
result = func(*args, **kwargs)
# Thêm chức năng sau khi gọi func
print("Đã gọi xong.")
return result
return wrapper
Dùng như sau:
@my_decorator
def say_hello():
print("Xin chào!")
say_hello()
Kết quả
Bắt đầu gọi hàm...
Xin chào!
Đã gọi xong.
II. Ví dụ thực tế
1. Log thời gian thực thi của một hàm
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"Hàm {func.__name__} chạy trong {end - start:.2f} giây")
return result
return wrapper
@timer
def slow_function():
time.sleep(2)
print("Xong việc rồi")
slow_function()
2. Kiểm tra phân quyền trước khi gọi hàm (giống middleware)
def require_admin(func):
def wrapper(user, *args, **kwargs):
if user != 'admin':
print("Không có quyền truy cập")
return None
return func(user, *args, **kwargs)
return wrapper
@require_admin
def view_dashboard(user):
print(f" Welcome {user}, đây là dashboard.")
view_dashboard("guest") # Không có quyền truy cập
view_dashboard("admin") # Welcome admin, đây là dashboard.
III. Decorator có tham số (Decorator Factory)
Ví dụ bạn muốn tạo decorator có thể truyền tham số:
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def hello():
print("Hi!")
hello()
Hi!
Hi!
Hi!
IV. Giữ metadata của hàm gốc (functools.wraps
)
Mặc định khi bạn dùng decorator, thông tin gốc của hàm như tên và docstring sẽ bị mất.
from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("Bọc hàm nè")
return func(*args, **kwargs)
return wrapper
V. Decorator trong Django và thực tế
Tên Decorator | Chức năng |
---|---|
@login_required |
Đảm bảo người dùng đã đăng nhập trước khi truy cập view |
@require_POST |
Chỉ cho phép method POST (dùng trong view) |
@csrf_exempt |
Bỏ qua kiểm tra CSRF (thường dùng khi làm API) |
@transaction.atomic |
Gói các thao tác DB trong một transaction an toàn |
from django.contrib.auth.decorators import login_required
@login_required
def dashboard(request):
return render(request, 'dashboard.html')
VI. Tóm lại
Khái niệm | Giải thích ngắn |
---|---|
Decorator | Hàm gói hàm khác, thêm chức năng mà không sửa hàm gốc |
Dùng @decorator_name |
Cú pháp gọn gàng để áp dụng |
functools.wraps() |
Giữ tên, docstring, v.v. của hàm gốc |
Có thể lồng nhau | Decorator A gói decorator B |
Tác giả: Đỗ Ngọc Tú
Công Ty Phần Mềm VHTSoft
Không có bình luận