Giới thiệu tổng quan về Decorator trong Python


Trong Python, một decorator là một mẫu thiết kế (Design Pattern) cho phép bạn chỉnh sửa chức năng của một hàm mà không làm thay đổi hàm gốc bằng cách đóng gói nó trong một hàm khác. Thông thường Decorator sẽ chỉnh sửa các tham số đầu vào (input) trước khi được thực thi trong hàm gốc hoặc chỉnh sửa kết quả (output) sau khi đã thực thi hàm gốc.

Theo như vinasupport.com tìm hiểu, Python hỗ trợ một số decorator có sẵn mà chúng ta thường gặp như @staticmethod hay @property… Chúng đều là những hàm decorator cơ bản của Python.

Một số công việc sau thường sử dụng decorator như là:

  • Bạn muốn ghi lại quá trình thực thi của một hàm nhằm mục đích gỡ lỗi.
  • Bạn cần khởi tạo (init) một số tài nguyên trước khi một hàm có thể hoạt động.
  • Bạn muốn dọn dẹp (cleanup) các đối tượng (object) sau khi một chức năng kết thúc.
  • Bạn muốn đo thời gian thực hiện của một hàm.
  • Ngoài ra quan trọng là nó sẽ giúp bạn giảm thời gian phát triển do tính sử dụng lại của Decorator.

Sau đây chúng tôi sẽ tạo 1 decorator cơ bản trong Python

Ví dụ 1: Chỉnh sửa dữ liệu đầu vào với decorator

def uppercase_first_letter(func):
    def wrapper(text):
        text = text.title()
        return func(text)
    return wrapper


@uppercase_first_letter
def print_text(text):
    print(text)


print_text('test')

Kết quả:

Hàm trên mục đích là viết hoa chữ đầu tiên của 1 đoạn văn bản được nhập vào.

Ở đây chúng tôi viết 1 hàm có tên là uppercase_first_letter(func) với đối số truyền vào là 1 hàm khác func ,

sau khi thực hiện chỉnh sửa đoạn văn bản truyền vào: text = text.title()

Thì chúng ta trả lại chính hàm đó: return func(text)

Cuối cùng là bất cứ hàm nào muốn sử dụng decorator này thì chỉ cần thiêm @uppercase_first_letter ở trên đầu là được.

Trường hợp bạn muốn chỉnh sửa output thì sao? Hãy xem ví dụ bên dưới.

Ví dụ 2: Chỉnh sửa dữ liệu đầu ra với decorator

def uppercase_first_letter(func):
    def wrapper(text):
        res = func(text)
        return res.title()
    return wrapper


@uppercase_first_letter
def my_text(text):
    return text


print(my_text('test'))

Ở ví dụ này, thay vì chỉnh sửa đầu vào thì chúng ta hãy cứ thực thi hàm gốc: res = func(text)

Ta thu được kết quả thì chỉnh sửa lại kết quả rồi trả lại kết quả khỏi decorator. return res.title()

Ví dụ 3: Truyền tham số vào Decorator trong Python

Giờ thì chúng ta thử tham khảo một hàm phực tạp hơn nhé!

def convert_argument_to_list(*convert_keys):
    """
    Convert argument to list decorator: Modify input parameter from int, string to list
    :param convert_keys:
    :return:
    """
    def decorator(f):
        def wrapper_accepting_arguments(*args, **kwargs):
            for key in kwargs.keys():
                if key in convert_keys:
                    value = kwargs.get(key)
                    # convert str "1,2,3,4" to list [1,2,3,4]
                    if isinstance(value, str):
                        kwargs[key] = list(set([int(item) for item in value.split(',')]))
            return f(*args, **kwargs)
        return wrapper_accepting_arguments
    return decorator


@convert_argument_to_list('ids')
def convert_string_to_list(ids=''):
    print(ids)


convert_string_to_list(ids='1,2,3,4')

Giống như ví dụ 1, hàm này sẽ chỉnh sửa input đầu vào và thực hiện nhiệm vụ phân tách 1 chuỗi ra 1 danh sách (list). Đồng thời nó chũng chỉ định key tham số nào của hàm thì mới thực hiện nhiệm vụ đó.

Kết quả:

Kết luận

Để hiểu về Decorator ban đầu khá khó để hiểu. Tuy nhiên nếu lắm được thì giúp bạn rất nhiều để lập trình nhanh hơn, hiệu quả hơn.

Nguồn vinasupport.com

             
SHARE

Bài viết liên quan

mode_edit Bình luận của bạn

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

account_circle
web