Tên chức năng in trang trí python

Bất kỳ ứng dụng sản xuất nào cũng có thể có một số hướng dẫn về cách thức và những gì cần được đăng nhập vào ứng dụng của bạn. Thông thường, những hướng dẫn này bắt nguồn từ các mẫu phổ biến trong ngành, chẳng hạn như “ghi nhật ký tất cả các trường hợp ngoại lệ”. Tuy nhiên, việc triển khai các hướng dẫn này được dành cho từng nhà phát triển và dẫn đến cùng một tập hợp các câu lệnh ghi nhật ký được lặp lại trong toàn bộ cơ sở mã. Chẳng hạn, để ghi nhật ký tất cả các ngoại lệ, bạn sẽ có một câu lệnh ghi nhật ký trong mỗi khối

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
6 ghi lại ngoại lệ và ghi nhật ký dưới cấp độ
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
7. Nhưng câu lệnh ghi nhật ký cho cùng một kịch bản có thể khác nhau giữa các nhà phát triển do phong cách phát triển cá nhân của họ. Ngoài giờ, điều này dẫn đến việc đăng nhập bị phân mảnh và không nhất quán trong ứng dụng. Hơn nữa, các nhà phát triển có thể mắc lỗi và bỏ lỡ việc ghi nhật ký ở những nơi cần thiết

Một cách tiếp cận để giảm bớt vấn đề này là sử dụng tính năng trang trí của Python. Bài viết này sẽ cung cấp một cái nhìn tổng quan ngắn gọn về các bộ trang trí và trình bày cách tạo một bộ trang trí để trừu tượng hóa các câu lệnh ghi nhật ký phổ biến này. Bạn có thể đọc thêm về các công cụ trang trí và nhiều cách chúng có thể được sử dụng trong Tài liệu cơ bản tuyệt vời này về Công cụ trang trí Python

trang trí là gì

Trình trang trí là một chức năng nhận một chức năng khác và mở rộng hành vi của nó mà không sửa đổi nó một cách rõ ràng. Chúng còn được gọi là hàm bậc cao

Các chức năng của Python là công dân hạng nhất. Điều này có nghĩa là các hàm có thể được truyền dưới dạng đối số hoặc có thể là đối tượng của phép gán. Vì vậy, nếu bạn có một hàm

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
8, bạn có thể sử dụng nó như bất kỳ đối tượng nào khác và đi sâu vào các thuộc tính của nó

def sum[a, b=10]:
    return a+b

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']

Vì các chức năng hoạt động giống như một đối tượng, bạn có thể gán

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
9 cho một chức năng khác. Sau đó, gọi
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
9 sẽ gọi hàm khác này thay vì hàm mà chúng ta đã xác định trước đó. Các bộ trang trí sử dụng hành vi này bằng cách gán cho
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
9 một chức năng mới lấy
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
9 làm tham số và bao bọc một số logic bổ sung xung quanh nó, do đó mở rộng nó mà không sửa đổi chính chức năng đó

def my_decorator[func]:
    def wrapper[*args, **kwargs]:
        # do something before `sum`
        result = func[*args, **kwargs]
        # do something after `sum`
        return result
    return wrapper

sum = my_decorator[sum]

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
0

Mẫu này phổ biến đến mức Python có một đường cú pháp để trang trí một chức năng. Vì vậy, thay vì

def my_decorator[func]:
    def wrapper[*args, **kwargs]:
        # do something before `sum`
        result = func[*args, **kwargs]
        # do something after `sum`
        return result
    return wrapper

sum = my_decorator[sum]
3, chúng ta có thể sử dụng ký hiệu
def my_decorator[func]:
    def wrapper[*args, **kwargs]:
        # do something before `sum`
        result = func[*args, **kwargs]
        # do something after `sum`
        return result
    return wrapper

sum = my_decorator[sum]
4 trên phương thức
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
9 như thế này -

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
4

Trình trang trí nhật ký

Chúng ta sẽ tạo một trình trang trí xử lý hai tình huống ghi nhật ký phổ biến - ghi nhật ký ngoại lệ dưới dạng LỖI và đối số phương thức ghi nhật ký dưới dạng nhật ký GỠ LỖI

Hãy bắt đầu bằng cách nắm bắt các ngoại lệ và ghi nhật ký bằng thư viện python

def my_decorator[func]:
    def wrapper[*args, **kwargs]:
        # do something before `sum`
        result = func[*args, **kwargs]
        # do something after `sum`
        return result
    return wrapper

sum = my_decorator[sum]
6

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
6

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
7

Ngoài việc thiết lập

def my_decorator[func]:
    def wrapper[*args, **kwargs]:
        # do something before `sum`
        result = func[*args, **kwargs]
        # do something after `sum`
        return result
    return wrapper

sum = my_decorator[sum]
7, chúng tôi cũng đã sử dụng @funcools. kết thúc tốt đẹp trang trí. Trình trang trí
def my_decorator[func]:
    def wrapper[*args, **kwargs]:
        # do something before `sum`
        result = func[*args, **kwargs]
        # do something after `sum`
        return result
    return wrapper

sum = my_decorator[sum]
8 cập nhật chức năng
def my_decorator[func]:
    def wrapper[*args, **kwargs]:
        # do something before `sum`
        result = func[*args, **kwargs]
        # do something after `sum`
        return result
    return wrapper

sum = my_decorator[sum]
9 để trông giống như
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
00. Trình trang trí
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
01 của chúng tôi hiện có thể được sử dụng trên bất kỳ chức năng nào để nắm bắt mọi ngoại lệ từ chức năng được bao bọc và ghi lại nó một cách nhất quán

Vì hàm

def my_decorator[func]:
    def wrapper[*args, **kwargs]:
        # do something before `sum`
        result = func[*args, **kwargs]
        # do something after `sum`
        return result
    return wrapper

sum = my_decorator[sum]
9 chấp nhận tất cả các đối số [
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
03], trình trang trí
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
01 có thể được mở rộng để nắm bắt tất cả các tham số được truyền cho hàm được trang trí. Chúng ta có thể làm điều này bằng cách lặp qua args và kwargs và nối chúng để tạo thành thông báo chuỗi để ghi nhật ký

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
6

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
7

Chúng tôi ghi nhật ký các tham số ở mức GỠ LỖI vì chúng tôi không muốn nhật ký của mình lộn xộn với tất cả các đối số chức năng. Ghi nhật ký gỡ lỗi có thể được bật trên hệ thống của chúng tôi khi cần thiết. Hãy nhớ rằng điều này sẽ ghi tất cả các giá trị đối số vào nhật ký bao gồm mọi dữ liệu PII hoặc bí mật

Trình trang trí ghi nhật ký cơ bản này có vẻ tốt và đã thực hiện những gì chúng tôi đặt ra ban đầu để đạt được. Miễn là một phương thức được trang trí bằng trình trang trí

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
01, chúng tôi sẽ ghi lại bất kỳ ngoại lệ nào được đưa ra bên trong nó và tất cả các đối số được truyền cho nó

Tuy nhiên, trong một dự án thực tế, bản thân

def my_decorator[func]:
    def wrapper[*args, **kwargs]:
        # do something before `sum`
        result = func[*args, **kwargs]
        # do something after `sum`
        return result
    return wrapper

sum = my_decorator[sum]
7 có thể được trừu tượng hóa thành lớp riêng của nó để khởi tạo trình ghi nhật ký dựa trên cấu hình nhất định [chẳng hạn như đẩy nhật ký lên đám mây chìm]. Trong trường hợp này, thật vô ích khi đăng nhập vào bảng điều khiển bằng cách tạo trình ghi nhật ký của riêng chúng tôi trong trình trang trí
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
01. Chúng tôi cần một cách để chuyển một
def my_decorator[func]:
    def wrapper[*args, **kwargs]:
        # do something before `sum`
        result = func[*args, **kwargs]
        # do something after `sum`
        return result
    return wrapper

sum = my_decorator[sum]
7 hiện có vào trình trang trí của chúng tôi khi chạy. Để làm điều này, chúng ta có thể mở rộng trình trang trí
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
01 để chấp nhận
def my_decorator[func]:
    def wrapper[*args, **kwargs]:
        # do something before `sum`
        result = func[*args, **kwargs]
        # do something after `sum`
        return result
    return wrapper

sum = my_decorator[sum]
7 làm đối số

Để bắt chước kịch bản này, chúng ta sẽ bắt đầu với việc có một lớp tạo bộ ghi nhật ký cho chúng ta. Bây giờ chúng ta sẽ tạo bộ ghi cơ bản nhưng bạn có thể tưởng tượng lớp cấu hình hành vi của bộ ghi theo yêu cầu

def sum[a, b=10]:
    return a+b
4

Vì tại thời điểm viết trình trang trí, chúng tôi không biết liệu chức năng cơ bản sẽ chuyển cho chúng tôi

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
41 hoặc
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
42 hay không có trình ghi nào cả, trình trang trí chung của chúng tôi sẽ có thể xử lý tất cả chúng

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
0

Đoạn mã trên trông khá đáng sợ nhưng hãy để tôi tóm tắt nó. Trình trang trí

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
01 hiện xử lý ba tình huống khác nhau -

  • Không có logger nào được thông qua. Đây là kịch bản tương tự những gì chúng tôi đã làm cho đến trước đó. Trình trang trí được sử dụng đơn giản như câu lệnh

    >>> sum
    
    >>> sum.__code__.co_varnames  # Names of local variables
    ['a', 'b']
    
    01 ở đầu hàm. Trong trường hợp này, decorator lấy một logger bằng cách gọi phương thức
    >>> sum
    
    >>> sum.__code__.co_varnames  # Names of local variables
    ['a', 'b']
    
    45 và sử dụng nó cho phần còn lại của phương thức

  • >>> sum
    
    >>> sum.__code__.co_varnames  # Names of local variables
    ['a', 'b']
    
    41 được thông qua. Trình trang trí
    >>> sum
    
    >>> sum.__code__.co_varnames  # Names of local variables
    ['a', 'b']
    
    01 của chúng tôi hiện có thể chấp nhận phiên bản của
    >>> sum
    
    >>> sum.__code__.co_varnames  # Names of local variables
    ['a', 'b']
    
    41 làm đối số. Sau đó, nó có thể gọi phương thức
    >>> sum
    
    >>> sum.__code__.co_varnames  # Names of local variables
    ['a', 'b']
    
    49 để tạo bộ ghi nhật ký lồng nhau và sử dụng phần còn lại của nó

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
1

  • >>> sum
    
    >>> sum.__code__.co_varnames  # Names of local variables
    ['a', 'b']
    
    42 được thông qua. Trong trường hợp thứ ba này, chúng ta có thể chuyển chính bộ ghi nhật ký thay vì chuyển lớp
    >>> sum
    
    >>> sum.__code__.co_varnames  # Names of local variables
    ['a', 'b']
    
    41

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
2

Chúng tôi vẫn chưa hoàn thành. Ngay cả ở dạng hiện tại, trình trang trí nhật ký của chúng tôi bị hạn chế. Một hạn chế là chúng ta phải có sẵn

def my_decorator[func]:
    def wrapper[*args, **kwargs]:
        # do something before `sum`
        result = func[*args, **kwargs]
        # do something after `sum`
        return result
    return wrapper

sum = my_decorator[sum]
7 hoặc
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
41 trước phương pháp mà chúng ta muốn trang trí. Nói cách khác, tham chiếu đến logger phải tồn tại trước khi phương thức tồn tại. Điều này có thể hoạt động trong trường hợp hàm mục tiêu là một phần của lớp và phương thức lớp
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
64 có thể khởi tạo trình ghi, nhưng nó sẽ không hoạt động với các hàm bên ngoài ngữ cảnh của lớp. Trong nhiều ứng dụng trong thế giới thực, chúng tôi sẽ không có từng mô-đun hoặc chức năng tạo trình ghi nhật ký của riêng chúng. Thay vào đó, chúng tôi có thể muốn chuyển bộ ghi nhật ký cho chính chức năng đó.
def my_decorator[func]:
    def wrapper[*args, **kwargs]:
        # do something before `sum`
        result = func[*args, **kwargs]
        # do something after `sum`
        return result
    return wrapper

sum = my_decorator[sum]
7 hoặc
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
41 sẽ là phần phụ thuộc được đưa vào các phương thức xuôi dòng. Nói cách khác, một chức năng có thể có bộ ghi được truyền cho nó trong tham số của nó

Nhưng nếu hàm là một phần của lớp thì

def my_decorator[func]:
    def wrapper[*args, **kwargs]:
        # do something before `sum`
        result = func[*args, **kwargs]
        # do something after `sum`
        return result
    return wrapper

sum = my_decorator[sum]
7 sẽ được đưa vào chính lớp đó chứ không phải vào mọi phương thức của lớp. Trong trường hợp này, chúng tôi muốn sử dụng bộ ghi có sẵn cho lớp của chúng tôi để thay thế

Vì vậy, mục tiêu của chúng tôi là nắm bắt

def my_decorator[func]:
    def wrapper[*args, **kwargs]:
        # do something before `sum`
        result = func[*args, **kwargs]
        # do something after `sum`
        return result
    return wrapper

sum = my_decorator[sum]
7 được truyền dưới dạng đối số cho hàm được trang trí hoặc được truyền cho hàm tạo lớp của hàm được trang trí của chúng tôi và sử dụng nó để ghi nhật ký từ chính trình trang trí. Bằng cách này, trình trang trí của chúng tôi có thể được tách rời hoàn toàn khỏi chính trình ghi nhật ký và sẽ sử dụng bất kỳ trình ghi nhật ký nào có sẵn cho phương thức cơ bản khi chạy

Để làm điều này, chúng tôi sẽ lặp lại đối số

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
69 và
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
70 và kiểm tra xem chúng tôi có nhận được
def my_decorator[func]:
    def wrapper[*args, **kwargs]:
        # do something before `sum`
        result = func[*args, **kwargs]
        # do something after `sum`
        return result
    return wrapper

sum = my_decorator[sum]
7 trong bất kỳ đối số nào không. Để kiểm tra xem hàm có phải là một phần của lớp hay không, chúng ta có thể kiểm tra xem đối số đầu tiên của
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
69 có thuộc tính
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
73 hay không. Nếu đối số đầu tiên có thuộc tính
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
73, chúng tôi sẽ lặp lại trên
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
75 và kiểm tra xem một trong những giá trị này có phải là bộ ghi của chúng tôi không. Cuối cùng nếu không có gì hoạt động, chúng tôi sẽ mặc định là phương thức
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
45

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
3

Trình trang trí ở trên đủ chung để hoạt động cho 2 kịch bản khác ngoài 3 kịch bản mà chúng ta đã thảo luận trước đây -

  • def my_decorator[func]:
        def wrapper[*args, **kwargs]:
            # do something before `sum`
            result = func[*args, **kwargs]
            # do something after `sum`
            return result
        return wrapper
    
    sum = my_decorator[sum]
    
    7 hoặc
    >>> sum
    
    >>> sum.__code__.co_varnames  # Names of local variables
    ['a', 'b']
    
    41 được chuyển sang phương thức trang trí

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
4

  • def my_decorator[func]:
        def wrapper[*args, **kwargs]:
            # do something before `sum`
            result = func[*args, **kwargs]
            # do something after `sum`
            return result
        return wrapper
    
    sum = my_decorator[sum]
    
    7 hoặc
    >>> sum
    
    >>> sum.__code__.co_varnames  # Names of local variables
    ['a', 'b']
    
    41 được truyền cho phương thức lớp
    >>> sum
    
    >>> sum.__code__.co_varnames  # Names of local variables
    ['a', 'b']
    
    64 lưu trữ chức năng được trang trí

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
5

Một điều bổ sung mà chúng tôi đã làm là bọc tất cả mã trước khi gọi hàm được trang trí

>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
00 trong một khối
>>> sum

>>> sum.__code__.co_varnames  # Names of local variables
['a', 'b']
63. Chúng tôi không muốn việc thực thi thất bại do sự cố khi ghi nhật ký ngay cả trước khi chức năng mục tiêu được gọi. Trong mọi trường hợp, logic ghi nhật ký của chúng tôi sẽ gây ra lỗi trong hệ thống

Sự kết luận

Trình trang trí ở trên là một điểm khởi đầu tốt và có thể được mở rộng hoặc đơn giản hóa theo yêu cầu. Nó làm giảm khả năng bỏ lỡ việc ghi nhật ký ngoại lệ và chuẩn hóa các thông báo lỗi trên toàn ứng dụng

Chúng ta có thể sử dụng print làm tên hàm trong Python không?

Hàm in Python[] . Thông báo có thể là một chuỗi, hoặc bất kỳ đối tượng nào khác, đối tượng sẽ được chuyển thành chuỗi trước khi ghi ra màn hình. The print[] function prints the specified message to the screen, or other standard output device. The message can be a string, or any other object, the object will be converted into a string before written to the screen.

Chức năng trang trí trong Python là gì?

Trình trang trí là mẫu thiết kế trong Python cho phép người dùng thêm chức năng mới vào đối tượng hiện có mà không sửa đổi cấu trúc của đối tượng . Trình trang trí thường được gọi trước khi định nghĩa chức năng bạn muốn trang trí.

Kiểu trả về của trang trí là gì?

Người trang trí chấp nhận một chức năng và trả về một chức năng . either True or False depending on whether that number is prime or not.

Hàm bao bọc trong Python là gì?

Trình bao hàm là công cụ hữu ích để sửa đổi hành vi của hàm . Trong Python, chúng được gọi là decorators. Trình trang trí cho phép chúng tôi mở rộng hành vi của hàm hoặc lớp mà không thay đổi triển khai ban đầu của hàm được bao bọc.

Chủ Đề