Chúng là gì và bạn có thể sử dụng chúng như thế nào?
Khi viết mã, đôi khi bạn sẽ cần mở rộng một chức năng mà không thực sự trực tiếp sửa đổi mã của nó. Trong tình huống này, người trang trí có thể giúp đỡ.
Trình trang trí là một loại chức năng đặc biệt bao quanh một chức năng khác. Chúng cho phép bạn thêm mã bổ sung trước và sau chức năng ban đầu, cung cấp một cách hay để mở rộng các chức năng hiện có.
Mục Lục
Các nhà trang trí làm việc như thế nào?
Các hàm Python là công dân hạng nhất, có nghĩa là bạn có thể gán chúng cho các biến, chuyển chúng làm đối số cho các hàm khác và trả về chúng từ các hàm. Những thuộc tính này tạo điều kiện thuận lợi cho việc tạo ra các trang trí.
Hàm trang trí trả về một hàm khác. Nó hoạt động như một siêu chức năng bổ sung chức năng bổ sung cho chức năng mục tiêu. Khi bạn trang trí một hàm, Python gọi hàm trang trí và chuyển hàm đích làm đối số.
Hàm trang trí có thể thực hiện bất kỳ hành động cần thiết nào trước và sau khi gọi hàm đích. Nó cũng có thể sửa đổi hành vi của hàm mục tiêu bằng cách trả về một hàm mới hoặc thay thế hoàn toàn hàm ban đầu.
Tạo một chức năng trang trí
Để tạo một trình trang trí, hãy xác định một hàm nhận một hàm mục tiêu làm đối số và trả về một hàm bao bọc. Hàm trình bao chứa chức năng bổ sung và lệnh gọi đến hàm đích.
def decorator_func(target_func):
def wrapper_func():
target_func()
return wrapper_func
Đây, decorator_func nhận target_func như một lý lẽ. Nó trở lại trình bao bọc_func cuộc gọi nào target_func Và chứa các chức năng bổ sung.
Trang trí một chức năng với Decorator
Để áp dụng trình trang trí cho chức năng đích, hãy sử dụng @ cú pháp và đặt trình trang trí ngay phía trên định nghĩa hàm đích.
@decorator_func
def my_function():
pass
Ở đây, decorator_func trang trí my_function. Vì vậy, bất cứ khi nào bạn sử dụng my_functionlệnh gọi Python decorator_func và vượt qua my_function như một lý lẽ.
Lưu ý rằng chức năng trang trí không sử dụng dấu ngoặc đơn mở và đóng.
Để rõ ràng, các @ cú pháp giống như cú pháp đường. Bạn có thể chuyển hàm mục tiêu trực tiếp đến hàm trang trí dưới dạng đối số:
func = decorator_func(my_function)
Xử lý các đối số chức năng trong Decorators
Để xử lý các đối số hàm trong trình trang trí, hãy sử dụng * lập luận Và **kwargs trong hàm bao bọc. Điều này cho phép trình trang trí chấp nhận bất kỳ số lượng đối số vị trí và từ khóa nào.
def decorator_func(target_func):
def wrapper_func(*args, **kwargs):
result = target_func(*args, **kwargs)
return result
return wrapper_func
Các * lập luận Và **kwargs ở trong trình bao bọc_func đảm bảo rằng trình trang trí có thể xử lý bất kỳ đối số nào bạn chuyển đến hàm đích.
Trang trí với các đối số
Người trang trí cũng có thể lấy lý lẽ của riêng họ. Điều này cung cấp cho bạn một cách linh hoạt hơn để trang trí các chức năng.
def my_decorator(num_times):
def wrapper(func):
def inner(*args, **kwargs):
for _ in range(num_times):
func(*args, **kwargs)
return inner
return wrapper@my_decorator(2)
def greet(name):
print(f"Hello, {name}.")
Các my_decorator hàm lấy một số (2) làm đối số và trả về một vỏ bánh chức năng. Hàm đó trả về một bên trong chức năng gọi chức năng trang trí (chào hỏi, trong trường hợp này) một số lần nhất định (2). Để có thể:
greet("Prince")
Sẽ in “Xin chào, Hoàng tử” hai lần.
Sử dụng thực tế của trang trí
Bạn có thể sử dụng trình trang trí cho nhiều mục đích, chẳng hạn như ghi nhật ký, lưu vào bộ nhớ đệm, xác thực đầu vào và tối ưu hóa hiệu suất.
Trình trang trí nhật ký
Bạn có thể sử dụng trình trang trí ghi nhật ký để ghi thông tin về việc thực thi một chức năng. Điều này có thể giúp gỡ lỗi hoặc theo dõi hành vi của các chức năng cụ thể.
import loggingdef my_logger(func):
def wrapper(*args, **kwargs):
logging.info("Entering function: %s", func.__name__)
result = func(*args, **kwargs)
logging.info("Exiting function: %s", func.__name__)
return result
return wrapper
Thời gian trang trí
Bạn có thể sử dụng một bộ trang trí thời gian để đo thời gian thực hiện của một chức năng. Nó hữu ích cho việc lập hồ sơ hoặc tối ưu hóa mã.
import timedef timing_decorator(target_func):
def wrapper_func(*args, **kwargs):
start_time = time.time()
result = target_func(*args, **kwargs)
end_time = time.time()
total = end_time - start_time
print(f"Function {target_func.__name__} took {total} seconds to run")
return result
return wrapper_func
Áp dụng các trang trí:
@my_logger
@timing_decorator
def bg_task(n):
print(f"Background Task, {n}.")
return "Result !!!"if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
print(bg_task("CPU is Dancing"))
Bây giờ, bạn sẽ thấy gỡ lỗi khi hàm chạy và tóm tắt thời gian chạy.
ủy quyền trang trí
Bạn có thể sử dụng trình trang trí ủy quyền để kiểm tra xem người dùng có các quyền cần thiết để truy cập một chức năng cụ thể hay không. Hầu hết các khung web đều sử dụng tính năng này để thêm một lớp bảo mật. Một ví dụ phổ biến là của Django @yêu cầu đăng nhập người trang trí.
def authorization_decorator(target_func):
def wrapper_func(*args, **kwargs):
if is_user_authorized():
result = target_func(*args, **kwargs)
return result
else:
raise PermissionError("Unauthorized access") return wrapper_func
Những ví dụ này minh họa một số trường hợp sử dụng phổ biến cho người trang trí. Bạn có thể tạo các công cụ trang trí cho nhiều mục đích khác nhau, tùy thuộc vào yêu cầu cụ thể của bạn.
Khái niệm trang trí nâng cao
Trang trí rất dễ thực hiện và sử dụng. Nhưng chúng cũng mạnh mẽ và có thể cung cấp khả năng kiểm soát và linh hoạt hơn nữa.
Trang trí dựa trên lớp
Ngoài các bộ trang trí dựa trên chức năng, Python cũng hỗ trợ các bộ trang trí dựa trên lớp.
Một trình trang trí dựa trên lớp là một lớp định nghĩa một __gọi__ phương pháp ma thuật, cho phép bạn sử dụng lớp như một công cụ trang trí.
class DecoratorClass:
def __init__(self, target_func):
self.target_func = target_func def __call__(self, *args, **kwargs):
print("Calling function")
result = self.target_func(*args, **kwargs)
print("Function called")
return result
Ví dụ này định nghĩa một lớp trang trí. Khi bạn trang trí một chức năng với lớp trang tríPython gọi __gọi__ phương pháp ma thuật, áp dụng chức năng của trình trang trí cho chức năng đích.
Các bộ trang trí dựa trên lớp có thể duy trì trạng thái qua nhiều cuộc gọi bằng cách lưu trữ thông tin trong các biến đối tượng. Điều này cho phép bạn triển khai trình trang trí tiên tiến và linh hoạt hơn.
Trình trang trí làm tổ và xâu chuỗi
Giả sử bạn cần kết hợp các loại chức năng khác nhau thành một đơn vị duy nhất cho các hành động liên quan trên một chức năng. Bạn có thể đạt được điều này bằng cách áp dụng nhiều trình trang trí cho một chức năng.
def decorator1(func):
def wrapper(*args, **kwargs):
print("Decorator1...")
return func(*args, **kwargs) return wrapper
def decorator2(func):
def wrapper(*args, **kwargs):
print("Decorator2...")
return func(*args, **kwargs)
return wrapper
@decorator1
@decorator2
def my_function(n):
print(n)
Ở đây, cả hai người trang trí1 Và người trang trí2 trang trí my_function. Bất cứ khi nào bạn sử dụng my_functionchức năng của người trang trí1 áp dụng đầu tiên, sau đó là của người trang trí2.
Một ví dụ phổ biến là khi bạn cần áp dụng một chỉ đăng yêu cầu và yêu cầu đăng nhập chức năng cho chế độ xem Django.
Lợi ích của người trang trí
Trang trí cung cấp một số lợi thế khiến chúng trở nên cần thiết trong nhiều dự án Python:
- Khả năng sử dụng lại mã: Thúc đẩy khả năng sử dụng lại mã bằng cách tách các mối quan tâm xuyên suốt khỏi logic cốt lõi.
- Nguyên tắc KHÔ: Tuân thủ nguyên tắc Không lặp lại chính mình bằng cách áp dụng cùng một chức năng cho nhiều chức năng mà không cần sao chép mã.
- Khả năng đọc và khả năng bảo trì: Nâng cao khả năng đọc mã và khả năng bảo trì bằng cách giữ cho chức năng chính tập trung và rõ ràng.
- Phong cách Pythonic: Phù hợp với phong cách Pythonic bằng cách nhấn mạnh mã rõ ràng, biểu cảm và dễ đọc.
Vì những lý do này, bạn nên tận dụng các công cụ trang trí nếu có thể.
Thực hành tốt nhất để sử dụng trang trí
Khi làm việc với người trang trí, bạn nên tuân theo một số phương pháp hay nhất:
- Giữ chức năng của trình trang trí tập trung vào một mối quan tâm cụ thể, chẳng hạn như ghi nhật ký hoặc bộ nhớ đệm. Điều này thúc đẩy mã mô-đun và làm cho các trình trang trí trở nên linh hoạt hơn.
- Làm cho các trình trang trí có thể định cấu hình bằng cách sử dụng các tham số và tránh các giá trị được mã hóa cứng. Điều này cho phép bạn tùy chỉnh hành vi của trình trang trí khi áp dụng nó cho các chức năng khác nhau.
- Cung cấp mô tả rõ ràng và ngắn gọn về mục đích của trình trang trí, các tham số của nó (nếu có) và hành vi dự kiến khi được áp dụng cho một chức năng.
- Nếu trình trang trí có bất kỳ tác dụng phụ nào, chẳng hạn như sửa đổi hành vi của chức năng hoặc giới thiệu các phụ thuộc bổ sung, hãy ghi lại rõ ràng những tác động này để tham khảo trong tương lai.
- Viết bài kiểm tra đơn vị cho người trang trí của bạn để đảm bảo họ hoạt động như bạn mong đợi. Thử nghiệm các kịch bản và trường hợp cạnh khác nhau để bao quát nhiều tình huống.
Làm việc với hàm trong Python
Trang trí là một trong những lĩnh vực cốt lõi trong đó các chức năng vượt trội. Nói chung, các hàm Python là một khối xây dựng cơ bản để tổ chức và sử dụng lại mã. Chúng cho phép bạn đóng gói chức năng, truyền dữ liệu và trả về kết quả.
Hiểu cách định nghĩa và sử dụng các hàm là điều cần thiết để lập trình Python hiệu quả.