Lợi thế của trang trí trong python là gì?

Trong hướng dẫn này, bạn sẽ tìm hiểu cách sử dụng trình trang trí Python trên một hàm. Trình trang trí Python là công cụ hữu ích giúp bạn sửa đổi hành vi của hàm. Tương tự, các bộ trang trí cho phép bạn nắm bắt các nguyên tắc lập trình Không lặp lại chính mình (DRY) cho các hoạt động phổ biến mà bạn muốn áp dụng cho nhiều chức năng

Đến cuối hướng dẫn này, bạn sẽ có một sự hiểu biết sâu sắc về

  • Cách trang trí Python hoạt động
  • Cách xâu chuỗi nhiều trình trang trí Python trên một chức năng
  • Một số lưu ý xung quanh việc đặt hàng các trang trí này

Bắt đầu nào

Mục lục

  • Trình trang trí Python là gì?
  • Sử dụng Trình trang trí Python để sửa đổi hành vi chức năng
  • Truyền đối số vào Trình trang trí Python
  • Sử dụng nhiều Trình trang trí Python
  • Sự kết luận
  • Tài nguyên bổ sung

Trình trang trí Python là gì?

Trình trang trí Python là các đoạn mã cho phép các hàm hiện có được thêm vào hoặc sửa đổi khi chúng chạy mà không sửa đổi định nghĩa hàm cơ bản. Điều này được gọi là siêu lập trình vì bản thân chương trình cố gắng sửa đổi một phần khác của chính nó khi chạy chương trình

Chúng ta có thể nghĩ về các trình trang trí là đường cú pháp - có nghĩa là chúng có thể thực hiện phức tạp hơn một thứ khác dễ chịu hơn về mặt cú pháp. Để tìm hiểu sâu hơn về các trình trang trí Python, hãy xem hành vi của hàm

Hàm Python là đối tượng. Điều này có nghĩa là chúng có thể được gán cho các biến khác (trong số nhiều thứ quan trọng khác). Hãy xem một ví dụ về điều này

def print_welcome():
    print('Welcome to datagy!')
    
some_variable = print_welcome()
some_variable

# Returns: Welcome to datagy!

Những gì chúng tôi đã làm ở trên được xác định chức năng chào mừng bạn đến với trang web. Từ đó, chúng tôi đã gán chức năng đó cho một biến 

def print_welcome():
    print('Welcome to datagy!')
    
def print_hello(func):
    def inner():
        print('Hello!')
        func()
    return inner

decorated = print_hello(print_welcome)
decorated()

# Returns:
# Hello!
# Welcome to datagy!
2. Cuối cùng, chúng ta chỉ đơn giản gọi biến đó là. Điều này khiến chức năng được thực thi

Bây giờ chúng ta đã hiểu rằng các hàm Python là các đối tượng, chúng ta có thể làm nhiều việc hơn là chỉ gọi chúng. Chúng tôi thậm chí có thể chuyển chúng vào một chức năng khác. Điều này có nghĩa là chúng ta có thể truyền hàm đó vào và trả về hàm đó

Hãy xem nó trông như thế nào

def print_welcome():
    print('Welcome to datagy!')
    
def print_hello(func):
    def inner():
        print('Hello!')
        func()
    return inner

decorated = print_hello(print_welcome)
decorated()

# Returns:
# Hello!
# Welcome to datagy!

Tuy nhiên, định dạng trên hơi khó đọc. Đây là nơi các nhà trang trí phát huy tác dụng. Chúng ta có thể thay thế chính ví dụ trên bằng cách đơn giản là tô điểm chức năng của mình, 

def print_welcome():
    print('Welcome to datagy!')
    
def print_hello(func):
    def inner():
        print('Hello!')
        func()
    return inner

decorated = print_hello(print_welcome)
decorated()

# Returns:
# Hello!
# Welcome to datagy!
0, bằng chức năng trang trí, 
def print_welcome():
    print('Welcome to datagy!')
    
def print_hello(func):
    def inner():
        print('Hello!')
        func()
    return inner

decorated = print_hello(print_welcome)
decorated()

# Returns:
# Hello!
# Welcome to datagy!
1. Hãy xem nó trông như thế nào

def print_hello(func):
    def inner():
        print('Hello!')
        func()
    return inner

@print_hello
def print_welcome():
    print('Welcome to datagy!')
    
print_welcome()

# Returns:
# Hello!
# Welcome to datagy!

Bằng cách này, chúng tôi có thể loại bỏ nhu cầu chuyển một chức năng sang một chức năng khác một cách rõ ràng. Trình trang trí Python xử lý điều này ngầm

Sử dụng Trình trang trí Python để sửa đổi hành vi chức năng

Trong phần này, hãy khám phá các trình trang trí Python từ quan điểm thực tế hơn

Sử dụng Trình trang trí Python cho các hàm thời gian

Để chứng minh tiện ích của chúng, hãy xây dựng một hàm nhận một hàm khác và tính thời gian thực hiện của nó. Ở đây, lợi ích của việc sử dụng trình trang trí là nó cho phép chúng ta tuân theo các nguyên tắc lập trình DRY (Đừng lặp lại chính mình). Chúng ta có thể chỉ cần trang trí nhiều chức năng với các bộ trang trí này để tính thời gian chạy của chúng

import time

def timeit(func):
    def timed():
        start = time.time()
        result = func()
        end = time.time()
        print(f'Program took {(end - start) * 1000}s to run')
        return result
    return timed

@timeit
def print_welcome():
    print('Welcome to datagy!')
    
print_welcome()
        
# Returns:
# Welcome to datagy!
# Program took 0.0s to run

Hãy chia nhỏ những gì chúng tôi đã làm ở trên

  1. Chúng ta đã định nghĩa một hàm 
    def print_welcome():
        print('Welcome to datagy!')
        
    def print_hello(func):
        def inner():
            print('Hello!')
            func()
        return inner
    
    decorated = print_hello(print_welcome)
    decorated()
    
    # Returns:
    # Hello!
    # Welcome to datagy!
    2 có một hàm khác
  2. Hàm này có một hàm bên trong khác, 
    def print_welcome():
        print('Welcome to datagy!')
        
    def print_hello(func):
        def inner():
            print('Hello!')
            func()
        return inner
    
    decorated = print_hello(print_welcome)
    decorated()
    
    # Returns:
    # Hello!
    # Welcome to datagy!
    3
  3. Hàm theo dõi thời gian bắt đầu, thực hiện chức năng trang trí, theo dõi thời gian kết thúc, tính chênh lệch và trả về kết quả
  4. Cuối cùng, chức năng bên ngoài trả về chức năng bên trong

Khi chúng tôi áp dụng chức năng trang trí này cho chức năng của mình, 

def print_welcome():
    print('Welcome to datagy!')
    
def print_hello(func):
    def inner():
        print('Hello!')
        func()
    return inner

decorated = print_hello(print_welcome)
decorated()

# Returns:
# Hello!
# Welcome to datagy!
0, đầu tiên lời chào mừng của chúng tôi được trả về và sau đó thời gian thực hiện được hiển thị

Sử dụng Python Decorators để ghi thông tin hữu ích vào Terminal

Tương tự như ví dụ trên, chúng ta có thể sử dụng decorator để in thông tin hữu ích ra terminal khi chạy chương trình. Ví dụ: chúng ta có thể muốn biết chức năng nào đang được chạy và thời gian hiện tại. Thông tin này cũng có thể được chuyển đến tệp nhật ký bằng trình trang trí, nhưng chúng tôi sẽ chỉ tập trung vào việc in nó ở đây

Hãy xem cách chúng ta có thể tạo một trình trang trí để thực hiện điều này

from datetime import datetime
def log_info(func):
    def inner():
        print(f'Starting run at {datetime.now()}')
        print(f'Running {func.__name__}')
        func()
    return inner

@log_info
def print_welcome():
    print('Welcome to datagy!')
    
print_welcome()
        
# Returns:
# Starting run at 2022-02-11 15:36:48.080846
# Running print_welcome
# Welcome to datagy!

Trong ví dụ trên, trước khi chạy chức năng, trình trang trí của chúng tôi sẽ in ngày và giờ hiện tại cũng như tên của chức năng sẽ được chạy. Điều này có thể hữu ích nếu bạn đang chạy các tập lệnh dài hơn và chỉ muốn biết chương trình của mình đang ở đâu

Truyền đối số vào Trình trang trí Python

Cho đến giờ, bạn đã học cách tạo một số công cụ trang trí Python hữu ích. Tuy nhiên, không ai trong số những người trang trí này có đối số được truyền vào chúng. Trong phần này, bạn sẽ tìm hiểu cách tạo trình trang trí Python chấp nhận đối số

Để làm điều này, chúng tôi sẽ cho phép giải nén ma thuật cú pháp Python. Bằng cách này, ý tôi là sử dụng func_name(*args, **kwargs), sẽ giải nén tất cả các đối số và tất cả các đối số từ khóa. Bằng cách sử dụng điều này trong trình trang trí của bạn, bạn đảm bảo rằng trình trang trí sẽ chấp nhận bất kỳ số lượng đối số hoặc đối số từ khóa nào. Điều này làm cho chúng thực tế hơn đáng kể để sử dụng nhiều lần

Hãy xem xét một ví dụ

def print_welcome():
    print('Welcome to datagy!')
    
def print_hello(func):
    def inner():
        print('Hello!')
        func()
    return inner

decorated = print_hello(print_welcome)
decorated()

# Returns:
# Hello!
# Welcome to datagy!
0

Cái hay của phương pháp trên là nó chấp nhận cả đối số vị trí và từ khóa. Do đó, chức năng sẽ chạy ngay cả khi chúng tôi thực thi nó ở bất kỳ định dạng nào bên dưới

  • def print_welcome():
        print('Welcome to datagy!')
        
    def print_hello(func):
        def inner():
            print('Hello!')
            func()
        return inner
    
    decorated = print_hello(print_welcome)
    decorated()
    
    # Returns:
    # Hello!
    # Welcome to datagy!
    5
  • def print_welcome():
        print('Welcome to datagy!')
        
    def print_hello(func):
        def inner():
            print('Hello!')
            func()
        return inner
    
    decorated = print_hello(print_welcome)
    decorated()
    
    # Returns:
    # Hello!
    # Welcome to datagy!
    6
  • def print_welcome():
        print('Welcome to datagy!')
        
    def print_hello(func):
        def inner():
            print('Hello!')
            func()
        return inner
    
    decorated = print_hello(print_welcome)
    decorated()
    
    # Returns:
    # Hello!
    # Welcome to datagy!
    7

Tương tự, nếu chúng ta áp dụng trình trang trí cho một hàm khác, giả sử một hàm nhận bốn đối số, thì trình trang trí sẽ hoạt động mà không gặp vấn đề gì. Hãy xem nó trông như thế nào

def print_welcome():
    print('Welcome to datagy!')
    
def print_hello(func):
    def inner():
        print('Hello!')
        func()
    return inner

decorated = print_hello(print_welcome)
decorated()

# Returns:
# Hello!
# Welcome to datagy!
4

Trong phần tiếp theo, bạn sẽ học cách sử dụng nhiều trình trang trí Python cho một chức năng

Sử dụng nhiều Trình trang trí Python

Một mẩu tin thú vị về các bộ trang trí Python là chúng thậm chí có thể bị xiềng xích. Điều này có nghĩa là bạn có thể áp dụng nhiều trình trang trí cho một chức năng. Để hiểu điều này, chúng tôi sẽ tập trung vào một ví dụ minh họa đơn giản để làm cho mã dễ theo dõi hơn

def print_welcome():
    print('Welcome to datagy!')
    
def print_hello(func):
    def inner():
        print('Hello!')
        func()
    return inner

decorated = print_hello(print_welcome)
decorated()

# Returns:
# Hello!
# Welcome to datagy!
5

Điều duy nhất mà các chức năng trang trí của chúng tôi làm là in ra số 1 và số 2. Bằng cách đặt decorator

def print_welcome():
    print('Welcome to datagy!')
    
def print_hello(func):
    def inner():
        print('Hello!')
        func()
    return inner

decorated = print_hello(print_welcome)
decorated()

# Returns:
# Hello!
# Welcome to datagy!
8 trước
def print_welcome():
    print('Welcome to datagy!')
    
def print_hello(func):
    def inner():
        print('Hello!')
        func()
    return inner

decorated = print_hello(print_welcome)
decorated()

# Returns:
# Hello!
# Welcome to datagy!
9, bạn đang bọc hàm bọc
def print_hello(func):
    def inner():
        print('Hello!')
        func()
    return inner

@print_hello
def print_welcome():
    print('Welcome to datagy!')
    
print_welcome()

# Returns:
# Hello!
# Welcome to datagy!
0 bằng
def print_hello(func):
    def inner():
        print('Hello!')
        func()
    return inner

@print_hello
def print_welcome():
    print('Welcome to datagy!')
    
print_welcome()

# Returns:
# Hello!
# Welcome to datagy!
1

Để minh họa điều này, bạn có thể chuyển đổi thứ tự để xem hành vi được sửa đổi như thế nào

def print_welcome():
    print('Welcome to datagy!')
    
def print_hello(func):
    def inner():
        print('Hello!')
        func()
    return inner

decorated = print_hello(print_welcome)
decorated()

# Returns:
# Hello!
# Welcome to datagy!
0

Bằng cách đặt trình trang trí

def print_welcome():
    print('Welcome to datagy!')
    
def print_hello(func):
    def inner():
        print('Hello!')
        func()
    return inner

decorated = print_hello(print_welcome)
decorated()

# Returns:
# Hello!
# Welcome to datagy!
9 trước, chức năng đó được tạo thành chức năng bên ngoài nhất

Sự kết luận

Trong hướng dẫn này, bạn đã tìm hiểu về các bộ trang trí Python, đại diện cho một đường cú pháp để lập trình siêu dữ liệu. Trình trang trí Python cho phép chúng tôi sửa đổi hành vi của chức năng và cho phép chúng tôi mở rộng các chức năng theo những cách khác nhau

Bạn đã học được decorator là gì và cách sử dụng chúng. Bạn cũng đã học cách cho phép truyền tham số vào trình trang trí Python. Cuối cùng, bạn đã học cách xâu chuỗi các trang trí và thứ tự của các trang trí này quan trọng như thế nào

Trình trang trí Python có cần thiết không?

Python được khen ngợi vì cú pháp rõ ràng và ngắn gọn, và các trình trang trí cũng không ngoại lệ. Nếu có bất kỳ hành vi nào phổ biến đối với nhiều chức năng, bạn có thể cần tạo một trình trang trí . Dưới đây là một số ví dụ khi chúng có thể có ích. Kiểm tra loại đối số trong thời gian chạy.

Trình trang trí hoạt động như thế nào trong Python?

Decorators cung cấp một cú pháp đơn giản để gọi các hàm bậc cao hơn. Theo định nghĩa, trình trang trí là hàm nhận một hàm khác và mở rộng hành vi của hàm sau mà không sửa đổi nó một cách rõ ràng .