DECORATORS Python: Thêm Siêu Năng Lực Cho Hàm Của Bạn
Xin chào bạn, những người lập trình Python đầy kí niệm! Hôm nay, chúng ta sẽ bơi lội vào thế giới thú vị của Decorators Python. Hãy tưởng tượng Decorators như những bọc bìa kỳ diệu có thể nâng cấp hàm của bạn với siêu năng lực. Thú vị phải không? Hãy cùng nhau bắt đầu hành trình này!
Decorators Là Gì?
Tưởng tượng bạn có một món quà được trang trí đẹp mắt. Giấy bọc không thay đổi quà bên trong, nhưng nó làm cho quà trông xinh hơn, phải không? Đó chính xác là điều gì Decorators làm cho hàm của bạn trong Python. Chúng bọc quanh hàm của bạn, thêm chức năng bổ sung mà không thay đổi hàm gốc của nó.
Hãy bắt đầu với một ví dụ đơn giản:
def my_decorator(func):
def wrapper():
print("Đang có điều gì đó xảy ra trước khi gọi hàm.")
func()
print("Đang có điều gì đó xảy ra sau khi gọi hàm.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
Nếu bạn chạy mã này, bạn sẽ thấy:
Đang có điều gì đó xảy ra trước khi gọi hàm.
Hello!
Đang có điều gì đó xảy ra sau khi gọi hàm.
Hãy phân tích:
- Chúng ta định nghĩa một hàm trang trí
my_decorator
nhận một hàm làm đối số. - Trong
my_decorator
, chúng ta định nghĩa một hàmwrapper
thêm một số hành vi trước và sau khi gọi hàm gốc. - Chúng ta sử dụng cú pháp
@my_decorator
để áp dụng trang trí của mình cho hàmsay_hello
. - Khi chúng ta gọi
say_hello()
, thực chất là nó đang gọi phiên bản bọc của hàm.
Điều đó thật tuyệt vời phải không? Chúng ta vừa thêm một số hành vi bổ sung vào hàm say_hello
của mình mà không cần sửa mã của nó!
Decorators Với Đối Số
Nhưng chờ chút, còn nhiều hơn nữa! Như thế nào nếu hàm của chúng ta nhận đối số? Không có vấn đề! Chúng ta có thể điều chỉnh trang trí của mình để xử lý điều đó:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Trước khi gọi hàm.")
result = func(*args, **kwargs)
print("Sau khi gọi hàm.")
return result
return wrapper
@my_decorator
def add(a, b):
return a + b
print(add(3, 5))
Điều này sẽ đầu ra:
Trước khi gọi hàm.
Sau khi gọi hàm.
8
Ở đây, *args
và **kwargs
cho phép trang trí của chúng ta hoạt động với bất kỳ số lượng đối số vị trí và từ khóa nào.
Trang Trí Độc Lập
Python đi kèm với một số trang trí độc lập rất hữu ích. Hãy khám phá chúng!
Trang Trí @classmethod
Trang trí @classmethod
được sử dụng để định nghĩa các phương thức hoạt động trên lớp chính, thay vì các thể hiện của lớp.
class Pizza:
def __init__(self, ingredients):
self.ingredients = ingredients
@classmethod
def margherita(cls):
return cls(['mozzarella', 'cà chua'])
@classmethod
def prosciutto(cls):
return cls(['mozzarella', 'cà chua', 'thịt giăm bông'])
print(Pizza.margherita().ingredients)
print(Pizza.prosciutto().ingredients)
Điều này sẽ đầu ra:
['mozzarella', 'cà chua']
['mozzarella', 'cà chua', 'thịt giăm bông']
Ở đây, margherita
và prosciutto
là các phương thức lớp để tạo và trả lại các thể hiện mới của Pizza với các nguyên liệu xác định sẵn.
Trang Trí @staticmethod
Các phương thức tĩnh là các phương thức không hoạt động trên thể hiện hoặc lớp. Chúng chỉ là các hàm bình thường xảy ra trong một lớp.
class Math:
@staticmethod
def add(a, b):
return a + b
print(Math.add(5, 10))
Điều này sẽ đầu ra:
15
Trang Trí @property
Trang trí @property
cho phép bạn định nghĩa các phương thức mà bạn có thể truy cập như các thuộc tính.
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@property
def area(self):
return 3.14 * self._radius ** 2
c = Circle(5)
print(c.radius)
print(c.area)
Điều này sẽ đầu ra:
5
78.5
Ở đây, chúng ta có thể truy cập radius
và area
như là các thuộc tính, nhưng chúng thực chất là các phương thức.
Trang Trí @functools.wraps
Trang trí này được sử dụng để bảo tồn metadata của hàm gốc khi tạo các trang trí.
from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
"""Đây là hàm bọc"""
return func(*args, **kwargs)
return wrapper
@my_decorator
def my_function():
"""Đây là hàm của tôi"""
pass
print(my_function.__name__)
print(my_function.__doc__)
Điều này sẽ đầu ra:
my_function
Đây là hàm của tôi
Nếu không có @wraps
, tên hàm và chuỗi tài liệu sẽ là của hàm bọc.
Kết Luận
Các trang trí là một tính năng mạnh mẽ trong Python cho phép bạn sửa đổi hoặc nâng cấp các hàm và phương thức. Chúng được sử dụng rộng rãi trong các khung công tác và thư viện để thêm chức năng như ghi nhật ký, kiểm soát truy cập, và nhiều hơn nữa.
Hãy nhớ, chìa khóa để nắm vững các trang trí là thực hành. Hãy thử tạo các trang trí của riêng bạn và áp dụng chúng cho các hàm khác nhau. Ngay lập tức, bạn sẽ bọc hàm của mình với siêu năng lực như một chuyên gia!
Dưới đây là bảng tóm tắt các trang trí mà chúng ta đã trình bày:
Trang Trí | Mục Đích |
---|---|
@classmethod |
Định nghĩa các phương thức hoạt động trên lớp chính |
@staticmethod |
Định nghĩa các phương thức không hoạt động trên thể hiện hoặc lớp |
@property |
Định nghĩa các phương thức có thể truy cập như các thuộc tính |
@functools.wraps |
Bảo tồn metadata của hàm gốc trong các trang trí |
Chúc bạn mãi mãi có các hàm luôn được trang trí đẹp mắt!
Credits: Image by storyset