Cách sử dụng Python Decorators để cải thiện chức năng

Trình trang trí Python là một cách mạnh mẽ và linh hoạt để sửa đổi hoặc cải thiện các hàm và phương thức. Trình trang trí cung cấp một cách để bao bọc một hàm bằng chức năng bổ sung, cho phép bạn mở rộng hành vi của nó mà không cần sửa đổi mã thực tế của nó. Bài viết này sẽ giới thiệu cho bạn khái niệm về trình trang trí, cách tạo và sử dụng chúng, và khám phá một số ví dụ thực tế.

Decorator là gì?

Decorator là một hàm lấy một hàm khác và mở rộng hành vi của hàm đó mà không sửa đổi rõ ràng. Trong Python, decorator thường được sử dụng để thêm chức năng như ghi nhật ký, kiểm soát truy cập hoặc đo lường hiệu suất cho các hàm hoặc phương thức hiện có. Decorator được áp dụng cho các hàm bằng cú pháp @decorator_name.

# Basic example of a decorator
def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

Cách thức hoạt động của Decorator

Khi bạn áp dụng trình trang trí cho một hàm, về cơ bản Python sẽ thực hiện các bước sau:

  1. Hàm trang trí được gọi với hàm ban đầu làm đối số.
  2. Hàm trang trí định nghĩa một hàm mới (thường được gọi là wrapper) giúp tăng cường hoặc sửa đổi hành vi của hàm ban đầu.
  3. Hàm trang trí trả về hàm mới.
  4. Khi hàm được trang trí được gọi, thực tế là nó sẽ gọi hàm mới được trả về bởi trình trang trí.

Tạo một Decorator đơn giản

Hãy tạo một trình trang trí đơn giản để đo thời gian thực hiện của một hàm. Điều này hữu ích cho việc kiểm tra hiệu suất và tối ưu hóa.

import time

def timing_decorator(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Execution time: {end_time - start_time} seconds")
        return result
    return wrapper

@timing_decorator
def slow_function():
    time.sleep(2)
    print("Function finished!")

slow_function()

Sử dụng Decorator với các đối số

Đôi khi, bạn có thể muốn truyền đối số cho trình trang trí của mình. Để đạt được điều này, bạn cần tạo một nhà máy trình trang trí—một hàm trả về một trình trang trí. Sau đây là ví dụ về trình trang trí lấy đối số để chỉ định một thông báo tùy chỉnh.

def custom_message_decorator(message):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print(message)
            return func(*args, **kwargs)
        return wrapper
    return decorator

@custom_message_decorator("Starting the function...")
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")

Trình trang trí cho các phương thức trong lớp

Decorator cũng có thể được sử dụng với các phương thức bên trong lớp. Các cách sử dụng phổ biến bao gồm ghi nhật ký các cuộc gọi phương thức, kiểm soát truy cập và lưu trữ kết quả. Sau đây là một ví dụ về việc sử dụng decorator để ghi nhật ký các cuộc gọi phương thức trong lớp.

def log_method_call(method):
    def wrapper(self, *args, **kwargs):
        print(f"Calling {method.__name__} with arguments {args} and keyword arguments {kwargs}")
        return method(self, *args, **kwargs)
    return wrapper

class MyClass:
    @log_method_call
    def my_method(self, x, y):
        print(f"Result: {x + y}")

obj = MyClass()
obj.my_method(5, 7)

Bộ trang trí chuỗi

Bạn có thể áp dụng nhiều decorator cho một hàm duy nhất. Chúng được áp dụng từ decorator trong cùng đến decorator ngoài cùng. Điều này cho phép bạn kết hợp các chức năng khác nhau lại với nhau. Sau đây là ví dụ về việc nối hai decorator:

def uppercase_decorator(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result.upper()
    return wrapper

def exclamation_decorator(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result + "!"
    return wrapper

@exclamation_decorator
@uppercase_decorator
def greet(name):
    return f"Hello, {name}"

print(greet("Alice"))

Phần kết luận

Decorator là một công cụ đa năng trong Python cho phép bạn cải thiện hoặc sửa đổi hành vi của các hàm và phương thức. Bằng cách sử dụng decorator, bạn có thể thêm chức năng có thể tái sử dụng trên toàn bộ cơ sở mã của mình mà không cần thay đổi logic cốt lõi của các hàm. Cho dù là để ghi nhật ký, tính thời gian hay sửa đổi đầu ra, decorator giúp giữ cho mã của bạn sạch sẽ và dễ bảo trì. Thực hành sử dụng decorator để trở nên thành thạo hơn và tận dụng sức mạnh của chúng trong các dự án Python của bạn.