Ghi nhớ python trang trí

Trình trang trí là công cụ rất mạnh mẽ và hữu ích trong Python vì nó cho phép các lập trình viên sửa đổi hành vi của hàm hoặc lớp. Trình trang trí cho phép chúng ta nhận tham số đầu vào là một hàm khác và mở rộng tính năng cho hàm đó mà không thay đổi nội dung của nó

Ví dụ về hàm Decorator trong Python

>>>Xem thêm. Hàm eval trong Python - Ví dụ và công dụng của hàm eval trong Python

Cú pháp của hàm Decorator trong Python

@gfg_decorator

chắc chắn hello_decorator[].  

in["Gfg"]

'''Mã trên tương đương với -

chắc chắn hello_decorator[].  

in["Gfg"]

hello_decorator = gfg_decorator[hello_decorator]'''

Trong ví dụ này, gfg_decorator là một hàm có thể gọi, hàm này có thể thêm một số mã vào đầu một số hàm có thể gọi được khác như hàm hello_decorator và trả về trình bao bọc hàm

>>>Tham khảo. Key learning set Python

Kỹ thuật ghi nhớ [Memoization] bằng cách sử dụng Decorator trong Python

Memoration Memoration

Ghi nhớ là một kỹ thuật ghi lại các kết quả trung gian để chúng có thể được sử dụng nhằm tránh tính toán lặp lại và tăng tốc độ cho chương trình. Ghi nhớ có thể được sử dụng để tối ưu hóa các chương trình sử dụng đệ quy. Trong Python, ghi nhớ có thể được thực hiện với sự trợ giúp của Decorator

Ví dụ về Ghi nhớ

Ví dụ về cách tính giai cấp thừa của một số

# Chương trình đệ quy đơn giản để tìm giai thừa

xác thực [số]

nếu số == 1

trả lại 1

khác

trả về số * thực tế [num-1]

in[thực tế[5]]

Chương trình như trên có thể sử dụng Trình trang trí để giải quyết như sau

# Chương trình giai thừa với ghi nhớ bằng cách sử dụng

# trang trí.  

# Hàm trang trí cho hàm 'f' được thông qua

# làm tham số

def memoize_factorial[f].  

bộ nhớ = {}

# Chức năng bên trong này có quyền truy cập vào bộ nhớ

# và 'f'

def bên trong [num].  

nếu num không có trong bộ nhớ.  

bộ nhớ [num] = f[num]

trả lại bộ nhớ [num]

trở lại bên trong

@memoize_factorial

xác thực [số].  

nếu số == 1.  

trả lại 1

khác.  

trả về số * thực tế [num-1]

in[thực tế[5]]

Giải thích về chức năng Memoization

Có thể giải thích ví dụ trên như sau

  1. Một hàm có tên memoize_factoria l đã được định nghĩa. Mục đích chính của nó là lưu trữ các kết quả trung gian trong biến được gọi là bộ nhớ
  2. Chức năng thứ hai được gọi thực tế là chức năng để tính toán giai đoạn thừa. Nó đã được chú thích bởi một người trang trí [hàm memoize_factorial]. Facto có quyền truy cập vào biến bộ nhớ.  
  3. Khi facto [5] được gọi, các phép toán đệ quy diễn ra bên ngoài việc lưu trữ các kết quả trung gian. Mỗi khi một tính năng được phép cần được thực hiện, nó sẽ được kiểm tra xem kết quả có sẵn trong bộ nhớ hay không. Nếu có, thì nó được sử dụng, đảo ngược, giá trị được tính toán và được lưu trữ trong bộ nhớ

Gỡ lỗi bằng Trình trang trí trong Python

Bạn có thể sử dụng Trình trang trí trong Python để loại bỏ lỗi bằng cách sử dụng funcools. wraps[] in standard library of Python.  

Ví dụ như sau

# nhập mô-đun

nhập hàm

# người trang trí

chắc chắn make_geek_happy [func].  

@functools. kết thúc tốt đẹp [func]

trình bao bọc def[].  

Neutral_message = func[]

happy_message = neutral_message + " Bạn đang hạnh phúc. "

trả lại happy_message

trả lại trình bao bọc

chắc chắn nói[].  

"""Trả về một tin nhắn trung lập"""

trả lại "Xin chào. "

positive_message = make_geek_happy[nói]

in[ positive_message[]]

in [nói. __Tên__]

in [nói. __doc__]

in [tích cực_message. __Tên__]

in [tích cực_message. __doc__]

Đầu ra nhận được như sau

Xin chào. Bạn đang hạnh phúc

nói

Trả về một tin nhắn trung lập

nói

Trả về một tin nhắn trung lập

Kết luận

Có thể thấy Trình trang trí trong Python là một công cụ tuyệt vời để đóng gói các mã xung quanh hàm và lớp. Bài viết trên giới thiệu về Decorator và một số chức năng của hàm này. Hy vọng bạn có thể áp dụng các kiến ​​thức này trong quá trình thiết lập với Python. Tìm hiểu thêm về Python và các ngôn ngữ lập trình khác thông qua các khóa học lập trình tại T3H

Trong hướng dẫn về trang trí này, chúng ta sẽ xem chúng là gì, cách tạo và sử dụng chúng. Trình trang trí 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, một trình trang trí là một 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

Điều này nghe có vẻ khó hiểu, nhưng thực sự không phải vậy, đặc biệt là sau khi bạn đã xem một số ví dụ về cách thức hoạt động của các công cụ trang trí. Bạn có thể tìm thấy tất cả các ví dụ từ bài viết này tại đây

Tiền thưởng miễn phí. Nhấp vào đây để truy cập vào hướng dẫn miễn phí "Sức mạnh của Trình trang trí Python" hiển thị cho bạn ba mẫu và kỹ thuật trang trí nâng cao mà bạn có thể sử dụng để viết các chương trình Pythonic rõ ràng hơn

Trang trí Cheat Sheet. Nhấp vào đây để có quyền truy cập vào bảng lừa đảo trang trí Python ba trang miễn phí tóm tắt các kỹ thuật được giải thích trong hướng dẫn này

Người trang trí Bảng điểm hỏi đáp. Nhấp vào đây để có quyền truy cập vào nhật ký trò chuyện dài 25 trang từ phiên Hỏi & Đáp về người trang trí Python của chúng tôi trong Slack Cộng đồng Python thực, nơi chúng tôi đã thảo luận về các câu hỏi phổ biến về người trang trí

cập nhật

  • 22/08/2018. Bản cập nhật lớn thêm nhiều ví dụ và trang trí cao cấp hơn
  • 01/12/2016. Các ví dụ được cập nhật lên Python 3 [v3. 5. 1] cú pháp và thêm một ví dụ mới
  • 01/11/2015. Đã thêm một lời giải thích ngắn gọn về trang trí
    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
    
    def say_whee[]:
        print["Whee!"]
    
    say_whee = my_decorator[say_whee]
    
    7

Chức năng

Trước khi bạn có thể hiểu về decorator, trước tiên bạn phải hiểu chức năng hoạt động như thế nào. Đối với mục đích của chúng tôi, một hàm trả về một giá trị dựa trên các đối số đã cho. Đây là một ví dụ rất đơn giản

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3

Nói chung, các hàm trong Python cũng có thể có tác dụng phụ thay vì chỉ biến đầu vào thành đầu ra. Hàm

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
8 là một ví dụ cơ bản về điều này. nó trả về
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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
9 trong khi có tác dụng phụ là xuất thứ gì đó ra bàn điều khiển. Tuy nhiên, để hiểu về decorator, chỉ cần nghĩ về hàm như một cái gì đó biến các đối số đã cho thành một giá trị là đủ.

Ghi chú. Trong lập trình chức năng, bạn [gần như] chỉ làm việc với các chức năng thuần túy mà không có tác dụng phụ. Mặc dù không phải là ngôn ngữ chức năng thuần túy, Python hỗ trợ nhiều khái niệm lập trình chức năng, bao gồm các hàm như đối tượng hạng nhất

Loại bỏ các quảng cáo

Đối tượng hạng nhất

Trong Python, hàm là đối tượng hạng nhất. Điều này có nghĩa là các hàm có thể được truyền xung quanh và được sử dụng làm đối số, giống như bất kỳ đối tượng nào khác [chuỗi, int, float, danh sách, v.v.]. Hãy xem xét ba chức năng sau

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]

Ở đây,

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
00 và
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
01 là các hàm thông thường yêu cầu tên được đặt dưới dạng chuỗi. Tuy nhiên, hàm
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
02 mong đợi một hàm làm đối số của nó. Ví dụ, chúng ta có thể truyền cho nó hàm
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
00 hoặc hàm
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
01

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
0

Lưu ý rằng

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
05 đề cập đến hai chức năng, nhưng theo những cách khác nhau.
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
02 và
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
07. Hàm
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
07 được đặt tên không có dấu ngoặc đơn. Điều này có nghĩa là chỉ một tham chiếu đến hàm được truyền. Chức năng không được thực thi. Mặt khác, hàm
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
02 được viết với dấu ngoặc đơn, vì vậy nó sẽ được gọi như bình thường

chức năng bên trong

Có thể định nghĩa các chức năng bên trong các chức năng khác. Các chức năng như vậy được gọi là các chức năng bên trong. Đây là một ví dụ về hàm có hai hàm bên trong

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
6

Điều gì xảy ra khi bạn gọi hàm

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
10? . Đầu ra sẽ như sau

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
8

Lưu ý rằng thứ tự xác định các hàm bên trong không quan trọng. Giống như bất kỳ chức năng nào khác, quá trình in chỉ diễn ra khi các chức năng bên trong được thực thi

Hơn nữa, các hàm bên trong không được xác định cho đến khi hàm cha được gọi. Chúng nằm trong phạm vi cục bộ tới

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
10. chúng chỉ tồn tại bên trong hàm
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
10 dưới dạng biến cục bộ. Hãy thử gọi
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
13. Bạn sẽ nhận được một lỗi

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
2

Bất cứ khi nào bạn gọi

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
10, các hàm bên trong
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
13 và
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
16 cũng được gọi. Nhưng do phạm vi cục bộ của chúng, chúng không khả dụng bên ngoài chức năng
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
10

Hàm trả về từ hàm

Python cũng cho phép bạn sử dụng các hàm làm giá trị trả về. Ví dụ sau trả về một trong các hàm bên trong từ hàm

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
10 bên ngoài

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
8

Lưu ý rằng bạn đang trả về

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
19 mà không có dấu ngoặc đơn. Nhớ lại rằng điều này có nghĩa là bạn đang trả về một tham chiếu đến hàm
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
19. Ngược lại
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
13 với dấu ngoặc đơn đề cập đến kết quả đánh giá chức năng. Điều này có thể được nhìn thấy trong ví dụ sau

>>>

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
2

Đầu ra hơi khó hiểu chỉ đơn giản có nghĩa là biến

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
22 đề cập đến hàm
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
13 cục bộ bên trong
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
10, trong khi
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
25 trỏ đến
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
16

Giờ đây, bạn có thể sử dụng

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
22 và
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
25 như thể chúng là các hàm thông thường, mặc dù không thể truy cập trực tiếp các hàm mà chúng trỏ tới

>>>

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
0

Cuối cùng, lưu ý rằng trong ví dụ trước, bạn đã thực thi các hàm bên trong hàm cha, chẳng hạn như

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
13. Tuy nhiên, trong ví dụ cuối cùng này, bạn đã không thêm dấu ngoặc đơn vào các hàm bên trong—
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
19—khi quay lại. Bằng cách đó, bạn có một tham chiếu đến từng chức năng mà bạn có thể gọi trong tương lai. Có lý?

Loại bỏ các quảng cáo

trang trí đơn giản

Bây giờ bạn đã thấy rằng các hàm cũng giống như bất kỳ đối tượng nào khác trong Python, bạn đã sẵn sàng để tiếp tục và xem con thú ma thuật đó là trình trang trí Python. Hãy bắt đầu với một ví dụ

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]

Bạn có đoán được điều gì sẽ xảy ra khi bạn gọi cho

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
31 không?

>>>

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
0

Để hiểu điều gì đang xảy ra ở đây, hãy xem lại các ví dụ trước. Chúng tôi thực sự chỉ áp dụng mọi thứ bạn đã học được cho đến nay

Cái gọi là trang trí xảy ra ở dòng sau

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
1

Trên thực tế, tên

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
32 hiện trỏ đến hàm bên trong
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
33. Hãy nhớ rằng bạn trả về
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
34 như một hàm khi bạn gọi
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
35

>>>

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
2

Tuy nhiên,

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
33 có tham chiếu đến
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
31 ban đầu là
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
38 và gọi hàm đó giữa hai lệnh gọi tới
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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
8

Đơn giản thôi. decorators bọc một chức năng, sửa đổi hành vi của nó

Trước khi tiếp tục, chúng ta hãy xem một ví dụ thứ hai. Vì

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
33 là một hàm Python thông thường nên cách trình trang trí sửa đổi một hàm có thể thay đổi linh hoạt. Để không làm phiền hàng xóm, ví dụ sau sẽ chỉ chạy mã trang trí vào ban ngày

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
3

Nếu bạn cố gọi cho

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
31 sau giờ đi ngủ, sẽ không có gì xảy ra

>>>

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
4

Cú pháp đặc biệt

Cách bạn trang trí

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
31 ở trên hơi rắc rối. Trước hết, bạn phải gõ tên
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
32 ba lần. Ngoài ra, phần trang trí bị ẩn một chút bên dưới định nghĩa của chức năng

Thay vào đó, Python cho phép bạn sử dụng các bộ trang trí theo cách đơn giản hơn với ký hiệu

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
44, đôi khi được gọi là cú pháp “chiếc bánh”. Ví dụ sau đây thực hiện chính xác điều tương tự như ví dụ trang trí đầu tiên

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
5

Vì vậy,

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
45 chỉ là một cách dễ dàng hơn để nói
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
46. Đó là cách bạn áp dụng một trình trang trí cho một chức năng

Loại bỏ các quảng cáo

Tái sử dụng đồ trang trí

Nhớ lại rằng một trình trang trí chỉ là một hàm Python thông thường. Tất cả các công cụ thông thường để tái sử dụng dễ dàng đều có sẵn. Hãy di chuyển trình trang trí sang mô-đun riêng của nó có thể được sử dụng trong nhiều chức năng khác

Tạo một tệp tên là

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
47 với nội dung sau

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
6

Ghi chú. Bạn có thể đặt tên cho chức năng bên trong của mình bất cứ điều gì bạn muốn và một tên chung chung như

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
33 thường không sao. Bạn sẽ thấy rất nhiều người trang trí trong bài viết này. Để tách chúng ra, chúng ta sẽ đặt tên hàm bên trong cùng tên với hàm trang trí nhưng có tiền tố
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
49

Bây giờ bạn có thể sử dụng trình trang trí mới này trong các tệp khác bằng cách nhập thông thường

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
7

Khi bạn chạy ví dụ này, bạn sẽ thấy rằng bản gốc

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
31 được thực thi hai lần

>>>

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
8

Tiền thưởng miễn phí. Nhấp vào đây để truy cập vào hướng dẫn miễn phí "Sức mạnh của Trình trang trí Python" hiển thị cho bạn ba mẫu và kỹ thuật trang trí nâng cao mà bạn có thể sử dụng để viết các chương trình Pythonic rõ ràng hơn

Các chức năng trang trí với các đối số

Giả sử rằng bạn có một hàm chấp nhận một số đối số. Bạn vẫn có thể trang trí nó?

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
9

Thật không may, chạy mã này gây ra lỗi

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
00

Vấn đề là hàm bên trong

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
51 không nhận bất kỳ đối số nào, nhưng
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
52 đã được truyền cho nó. Bạn có thể khắc phục điều này bằng cách cho phép
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
51 chấp nhận một đối số, nhưng sau đó nó sẽ không hoạt động đối với hàm
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
31 mà bạn đã tạo trước đó

Giải pháp là sử dụng

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
55 và
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
56 trong hàm bao bọc bên trong. Sau đó, nó sẽ chấp nhận một số đối số vị trí và từ khóa tùy ý. Viết lại
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
47 như sau

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
01

Hàm bên trong

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
51 hiện chấp nhận bất kỳ số lượng đối số nào và chuyển chúng vào hàm mà nó trang trí. Bây giờ cả hai ví dụ về
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
31 và
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
60 của bạn đều hoạt động

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
02

Loại bỏ các quảng cáo

Trả về các giá trị từ các chức năng được trang trí

Điều gì xảy ra với giá trị trả về của các chức năng được trang trí? . Giả sử bạn trang trí một chức năng đơn giản như sau

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
03

Cố gắng sử dụng nó

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
04

Rất tiếc, trình trang trí của bạn đã ăn giá trị trả về từ hàm

Bởi vì

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
61 không trả về giá trị một cách rõ ràng, cuộc gọi
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
62 đã kết thúc trả về
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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
9

Để khắc phục điều này, bạn cần đảm bảo hàm bao bọc trả về giá trị trả về của hàm trang trí. Thay đổi tệp

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
47 của bạn

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
05

Giá trị trả về từ lần thực thi cuối cùng của hàm được trả về

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
06

Bạn là ai, thực sự?

Một tiện lợi lớn khi làm việc với Python, đặc biệt là trong shell tương tác, là khả năng xem xét nội tâm mạnh mẽ của nó. Nội quan là khả năng của một đối tượng biết về các thuộc tính của chính nó trong thời gian chạy. Chẳng hạn, một hàm biết tên và tài liệu của chính nó

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
07

Việc xem xét nội tâm cũng hoạt động đối với các chức năng mà bạn tự xác định

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
08

Tuy nhiên, sau khi được trang trí,

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
31 đã rất bối rối về danh tính của mình. Bây giờ nó báo cáo là hàm bên trong
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
51 bên trong trình trang trí
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
67. Mặc dù đúng về mặt kỹ thuật, đây không phải là thông tin hữu ích lắm

Để khắc phục điều này, các nhà trang trí nên sử dụng trình trang trí

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
68, điều này sẽ lưu giữ thông tin về chức năng ban đầu. Cập nhật lại
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
47

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
09

Bạn không cần thay đổi bất cứ điều gì về chức năng

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
31 được trang trí

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
60

Tốt hơn nhiều. Bây giờ

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
31 vẫn là chính nó sau khi trang trí

Chi tiết kỹ thuật. Trình trang trí

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
68 sử dụng hàm
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
73 để cập nhật các thuộc tính đặc biệt như
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
74 và
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
75 được sử dụng trong phần nội quan

Loại bỏ các quảng cáo

Một vài ví dụ trong thế giới thực

Hãy xem xét một vài ví dụ hữu ích hơn về trang trí. Bạn sẽ nhận thấy rằng chúng sẽ chủ yếu tuân theo cùng một khuôn mẫu mà bạn đã học cho đến nay

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
61

Công thức này là một mẫu soạn sẵn tốt để xây dựng các công cụ trang trí phức tạp hơn

Ghi chú. Trong các ví dụ sau, chúng tôi sẽ giả định rằng các bộ trang trí này cũng được lưu trong tệp

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
47 của bạn. Nhắc lại rằng bạn có thể tải xuống tất cả các ví dụ trong hướng dẫn này

chức năng thời gian

Hãy bắt đầu bằng cách tạo một trình trang trí

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
77. Nó sẽ đo thời gian một chức năng cần để thực thi và in thời lượng ra bàn điều khiển. Đây là mã

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
62

Trình trang trí này hoạt động bằng cách lưu trữ thời gian ngay trước khi chức năng bắt đầu chạy [tại dòng được đánh dấu

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
78] và ngay sau khi chức năng kết thúc [tại
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
79]. Thời gian mà chức năng cần sau đó là sự khác biệt giữa hai [tại
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
80]. Chúng tôi sử dụng hàm
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
81, hàm này thực hiện tốt công việc đo khoảng thời gian. Dưới đây là một số ví dụ về thời gian

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
63

Chạy nó cho mình. Làm việc thông qua từng dòng mã. Hãy chắc chắn rằng bạn hiểu nó hoạt động như thế nào. Tuy nhiên, đừng lo lắng nếu bạn không hiểu. Trang trí là những sinh vật tiên tiến. Cố gắng ngủ trên đó hoặc tạo một bản vẽ của chương trình

Ghi chú. Trình trang trí

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
77 rất tuyệt nếu bạn chỉ muốn có ý tưởng về thời gian chạy các chức năng của mình. Nếu bạn muốn thực hiện các phép đo mã chính xác hơn, thay vào đó, bạn nên xem xét mô-đun
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
83 trong thư viện chuẩn. Nó tạm thời tắt tính năng thu gom rác và chạy nhiều thử nghiệm để loại bỏ tiếng ồn khỏi các lệnh gọi hàm nhanh

Mã gỡ lỗi

Trình trang trí

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
84 sau đây sẽ in các đối số mà một hàm được gọi cùng với giá trị trả về của nó mỗi khi hàm được gọi

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
64

Chữ ký được tạo bằng cách nối các biểu diễn chuỗi của tất cả các đối số. Các số trong danh sách sau tương ứng với các nhận xét được đánh số trong mã

  1. Tạo một danh sách các đối số vị trí. Sử dụng
    def say_hello[name]:
        return f"Hello {name}"
    
    def be_awesome[name]:
        return f"Yo {name}, together we are the awesomest!"
    
    def greet_bob[greeter_func]:
        return greeter_func["Bob"]
    
    85 để có được một chuỗi đẹp đại diện cho mỗi đối số
  2. Tạo một danh sách các đối số từ khóa. Chuỗi f định dạng mỗi đối số là
    def say_hello[name]:
        return f"Hello {name}"
    
    def be_awesome[name]:
        return f"Yo {name}, together we are the awesomest!"
    
    def greet_bob[greeter_func]:
        return greeter_func["Bob"]
    
    86 trong đó mã xác định
    def say_hello[name]:
        return f"Hello {name}"
    
    def be_awesome[name]:
        return f"Yo {name}, together we are the awesomest!"
    
    def greet_bob[greeter_func]:
        return greeter_func["Bob"]
    
    87 có nghĩa là
    def say_hello[name]:
        return f"Hello {name}"
    
    def be_awesome[name]:
        return f"Yo {name}, together we are the awesomest!"
    
    def greet_bob[greeter_func]:
        return greeter_func["Bob"]
    
    85 được sử dụng để biểu thị giá trị
  3. Danh sách các đối số vị trí và từ khóa được nối với nhau thành một chuỗi chữ ký với mỗi đối số được phân tách bằng dấu phẩy
  4. Giá trị trả về được in sau khi hàm được thực thi

Hãy xem cách trình trang trí hoạt động trong thực tế bằng cách áp dụng nó cho một hàm đơn giản với một vị trí và một đối số từ khóa

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
65

Lưu ý cách trình trang trí

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
84 in chữ ký và giá trị trả về của hàm
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
90

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
66

Ví dụ này có vẻ không hữu ích ngay lập tức vì trình trang trí

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
84 chỉ lặp lại những gì bạn vừa viết. Nó mạnh hơn khi áp dụng cho các chức năng tiện lợi nhỏ mà bạn không tự gọi trực tiếp

Ví dụ sau đây tính toán một giá trị gần đúng với hằng số toán học e

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
67

Ví dụ này cũng cho thấy cách bạn có thể áp dụng một trình trang trí cho một chức năng đã được xác định. Phép tính gần đúng của e dựa trên khai triển chuỗi sau

Khi gọi hàm

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
92, bạn có thể thấy trình trang trí
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
84 đang hoạt động

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
68

Trong ví dụ này, bạn nhận được một giá trị gần đúng với giá trị thực e = 2. 718281828, chỉ thêm 5 số hạng

Loại bỏ các quảng cáo

Làm chậm mã

Ví dụ tiếp theo này có vẻ không hữu ích lắm. Tại sao bạn muốn làm chậm mã Python của mình? . Trình trang trí

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
94 sẽ ngủ một giây trước khi nó gọi chức năng trang trí

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
69

Để xem tác dụng của trình trang trí

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
94, bạn thực sự cần phải tự mình chạy ví dụ

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
80

Ghi chú. Hàm

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
96 là một hàm đệ quy. Nói cách khác, đó là một chức năng gọi chính nó. Để tìm hiểu thêm về các hàm đệ quy trong Python, hãy xem hướng dẫn của chúng tôi về Tư duy đệ quy trong Python

Trình trang trí

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
94 luôn ngủ trong một giây. Sau này, bạn sẽ thấy cách kiểm soát tốc độ bằng cách chuyển đối số cho trình trang trí

Đăng ký plugin

Người trang trí không cần phải bao bọc chức năng mà họ đang trang trí. Họ cũng có thể chỉ cần đăng ký rằng một chức năng tồn tại và trả lại nó khi chưa mở gói. Điều này có thể được sử dụng, ví dụ, để tạo ra một kiến ​​trúc plug-in trọng lượng nhẹ

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
81

Trình trang trí

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
98 chỉ đơn giản là lưu trữ một tham chiếu đến chức năng được trang trí trong toàn cầu
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
99 dict. Lưu ý rằng bạn không phải viết một hàm bên trong hoặc sử dụng
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
68 trong ví dụ này vì bạn đang trả về hàm ban đầu chưa sửa đổi

Hàm

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
001 chọn ngẫu nhiên một trong các hàm đã đăng ký để sử dụng. Lưu ý rằng từ điển
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
99 đã chứa các tham chiếu đến từng đối tượng chức năng được đăng ký làm plugin

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
82

Lợi ích chính của kiến ​​trúc plugin đơn giản này là bạn không cần duy trì danh sách các plugin tồn tại. Danh sách đó được tạo khi các plugin tự đăng ký. Điều này làm cho việc thêm một plugin mới trở nên tầm thường. chỉ cần xác định chức năng và trang trí nó bằng

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
98

Nếu bạn đã quen thuộc với

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
004 trong Python, bạn có thể thấy một số điểm tương đồng về cách thức hoạt động của kiến ​​trúc plugin.
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
004 cấp quyền truy cập vào tất cả các biến toàn cục trong phạm vi hiện tại, bao gồm cả plugin của bạn

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
83

Sử dụng trình trang trí

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
98, bạn có thể tạo danh sách các biến thú vị được quản lý của riêng mình, chọn thủ công một số hàm từ
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
004 một cách hiệu quả

Người dùng đã đăng nhập chưa?

Ví dụ cuối cùng trước khi chuyển sang một số trình trang trí đẹp hơn thường được sử dụng khi làm việc với khung web. Trong ví dụ này, chúng tôi đang sử dụng Flask để thiết lập trang web

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
008 chỉ hiển thị với người dùng đã đăng nhập hoặc được xác thực

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
84

Mặc dù điều này đưa ra ý tưởng về cách thêm xác thực vào khung web của bạn, nhưng thông thường bạn không nên tự mình viết các loại trình trang trí này. Đối với Flask, bạn có thể sử dụng tiện ích mở rộng Flask-Login để bổ sung thêm tính năng và bảo mật

Loại bỏ các quảng cáo

trang trí ưa thích

Cho đến giờ, bạn đã biết cách tạo các bộ trang trí đơn giản. Bạn đã hiểu khá rõ về decorator là gì và cách chúng hoạt động. Vui lòng tạm dừng bài viết này để thực hành mọi thứ bạn đã học

Trong phần thứ hai của hướng dẫn này, chúng ta sẽ khám phá các tính năng nâng cao hơn, bao gồm cách sử dụng các tính năng sau

  • Trang trí lớp học
  • Một số trang trí trên một chức năng
  • Trang trí với đối số
  • Trình trang trí có thể tùy ý lấy đối số
  • trang trí nhà nước
  • Các lớp học như trang trí

trang trí lớp học

Có hai cách khác nhau để bạn có thể sử dụng các công cụ trang trí trên các lớp. Cái đầu tiên rất gần với những gì bạn đã làm với các hàm. bạn có thể trang trí các phương thức của một lớp. Đây là một trong những động lực để giới thiệu những người trang trí trở lại trong ngày

Một số trình trang trí thường được sử dụng thậm chí được tích hợp sẵn trong Python là

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
009,
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
010 và
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
011. Các trình trang trí
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
009 và
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
010 được sử dụng để xác định các phương thức bên trong một không gian tên lớp không được kết nối với một thể hiện cụ thể của lớp đó. Trình trang trí
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
011 được sử dụng để tùy chỉnh getters và setters cho các thuộc tính lớp. Mở rộng hộp bên dưới để biết ví dụ sử dụng các công cụ trang trí này

Ví dụ sử dụng trình trang trí lớp tích hợp sẵnHiển thị/Ẩn

Định nghĩa sau đây của một lớp

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
015 sử dụng các bộ trang trí
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
009,
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
010 và
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
011

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
85

Trong lớp học này

  • >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    019 là một phương pháp thông thường
  • >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    020 là một thuộc tính có thể thay đổi. nó có thể được đặt thành một giá trị khác. Tuy nhiên, bằng cách xác định một phương thức setter, chúng ta có thể thực hiện một số kiểm tra lỗi để đảm bảo rằng nó không được đặt thành một số âm vô nghĩa. Thuộc tính được truy cập dưới dạng thuộc tính không có dấu ngoặc đơn
  • >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    021 là một tài sản bất biến. không thể thay đổi các thuộc tính không có phương thức
    >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    022. Mặc dù nó được định nghĩa là một phương thức, nhưng nó có thể được truy xuất dưới dạng một thuộc tính mà không cần dấu ngoặc đơn
  • >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    023 là một phương thức lớp. Nó không bị ràng buộc với một trường hợp cụ thể của
    >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    015. Các phương thức lớp thường được sử dụng làm phương thức xuất xưởng có thể tạo các thể hiện cụ thể của lớp
  • >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    025 là một phương thức tĩnh. Nó không thực sự phụ thuộc vào lớp
    >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    015, ngoại trừ việc nó là một phần của không gian tên của nó. Các phương thức tĩnh có thể được gọi trên một thể hiện hoặc lớp

Ví dụ, lớp

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
015 có thể được sử dụng như sau

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
86

Hãy định nghĩa một lớp nơi chúng ta trang trí một số phương thức của nó bằng cách sử dụng các bộ trang trí

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
84 và
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
77 từ trước đó

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
87

Sử dụng lớp này, bạn có thể thấy tác dụng của các trang trí

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
88

Một cách khác để sử dụng các công cụ trang trí trong lớp học là trang trí cho cả lớp. Ví dụ, điều này được thực hiện trong mô-đun

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
030 mới trong Python 3. 7

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
89

Ý nghĩa của cú pháp tương tự như các bộ trang trí chức năng. Trong ví dụ trên, bạn có thể đã trang trí bằng cách viết

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
031

Một cách sử dụng phổ biến của các công cụ trang trí lớp là một giải pháp thay thế đơn giản hơn cho một số trường hợp sử dụng siêu dữ liệu. Trong cả hai trường hợp, bạn đang thay đổi định nghĩa của một lớp một cách linh hoạt

Viết một trình trang trí lớp rất giống với viết một trình trang trí chức năng. Sự khác biệt duy nhất là trình trang trí sẽ nhận một lớp chứ không phải một hàm làm đối số. Trên thực tế, tất cả các trình trang trí bạn thấy ở trên sẽ hoạt động như các trình trang trí lớp. Khi bạn đang sử dụng chúng trên một lớp thay vì một chức năng, tác dụng của chúng có thể không như bạn muốn. Trong ví dụ sau, trình trang trí

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
77 được áp dụng cho một lớp

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
20

Trang trí một lớp học không trang trí các phương thức của nó. Nhớ lại rằng

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
77 chỉ là viết tắt của
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
034

Ở đây,

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
77 chỉ đo thời gian cần thiết để khởi tạo lớp

>>>

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
21

Sau đó, bạn sẽ thấy một ví dụ định nghĩa một trình trang trí lớp phù hợp, cụ thể là

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
036, đảm bảo rằng chỉ có một thể hiện của một lớp

Loại bỏ các quảng cáo

Đồ trang trí làm tổ

Bạn có thể áp dụng một số trình trang trí cho một chức năng bằng cách xếp chồng chúng lên nhau

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
22

Hãy nghĩ về điều này khi các trình trang trí được thực hiện theo thứ tự chúng được liệt kê. Nói cách khác,

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
84 gọi
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
038, gọi
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
60 hoặc
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
040

>>>

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
23

Quan sát sự khác biệt nếu chúng ta thay đổi thứ tự của

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
84 và
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
038

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
24

Trong trường hợp này,

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
038 cũng sẽ được áp dụng cho
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
84

>>>

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
25

Trang trí với các đối số

Đôi khi, thật hữu ích khi chuyển đối số cho người trang trí của bạn. Chẳng hạn,

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
038 có thể được mở rộng thành một trình trang trí
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
046. Số lần để thực hiện chức năng trang trí sau đó có thể được đưa ra như một đối số

Điều này sẽ cho phép bạn làm một cái gì đó như thế này

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
26

>>>

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
27

Hãy suy nghĩ về cách bạn có thể đạt được điều này

Cho đến nay, tên được viết sau

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
44 đã đề cập đến một đối tượng chức năng có thể được gọi bằng một chức năng khác. Để nhất quán, sau đó bạn cần
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
048 để trả về một đối tượng hàm có thể hoạt động như một công cụ trang trí. May mắn thay, bạn đã biết cách trả về hàm. Nói chung, bạn muốn một cái gì đó như sau

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
28

Thông thường, trình trang trí tạo và trả về một hàm bao bọc bên trong, do đó, viết đầy đủ ví dụ ra sẽ cung cấp cho bạn một hàm bên trong bên trong một hàm bên trong. Mặc dù điều này nghe có vẻ giống như chương trình tương đương với bộ phim Inception, nhưng chúng tôi sẽ gỡ rối tất cả trong giây lát

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
29

Có vẻ hơi lộn xộn, nhưng hiện tại chúng tôi chỉ đặt cùng một mẫu trang trí mà bạn đã thấy nhiều lần bên trong một

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
049 bổ sung xử lý các đối số cho trình trang trí. Hãy bắt đầu với chức năng trong cùng

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
80

Hàm

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
050 này nhận các đối số tùy ý và trả về giá trị của hàm được trang trí,
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
051. Hàm bao bọc này cũng chứa vòng lặp gọi hàm được trang trí
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
052 lần. Điều này không khác với các chức năng bao bọc trước đó mà bạn đã thấy, ngoại trừ việc nó đang sử dụng tham số
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
052 phải được cung cấp từ bên ngoài

Một bước ra ngoài, bạn sẽ tìm thấy chức năng trang trí

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
81

Một lần nữa,

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
054 trông giống hệt các hàm trang trí mà bạn đã viết trước đó, ngoại trừ việc nó được đặt tên khác. Đó là bởi vì chúng ta đặt tên cơ sở—
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
055—cho hàm ngoài cùng, là hàm mà người dùng sẽ gọi

Như bạn đã thấy, hàm ngoài cùng trả về một tham chiếu đến hàm trang trí

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
82

Có một vài điều tế nhị xảy ra trong hàm

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
055

  • Xác định
    >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    054 là một hàm bên trong có nghĩa là
    >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    055 sẽ tham chiếu đến một đối tượng hàm—
    >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    059. Trước đó, chúng tôi đã sử dụng
    >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    060 không có dấu ngoặc đơn để chỉ đối tượng chức năng. Các dấu ngoặc đơn được thêm vào là cần thiết khi xác định các trình trang trí lấy đối số
  • Đối số
    >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    052 dường như không được sử dụng trong chính
    >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    055. Nhưng bằng cách chuyển
    >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    052, một bao đóng được tạo trong đó giá trị của
    >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    052 được lưu trữ cho đến khi nó được sử dụng sau bởi
    >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    050

Với mọi thứ đã được thiết lập, hãy xem kết quả có như mong đợi không

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
26

>>>

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
27

Chỉ là kết quả mà chúng tôi đang hướng tới

Loại bỏ các quảng cáo

Làm ơn cho cả hai, nhưng đừng bận tâm đến bánh mì

Với một chút cẩn thận, bạn cũng có thể xác định các trình trang trí có thể được sử dụng cả khi có và không có đối số. Rất có thể, bạn không cần điều này, nhưng thật tuyệt khi có sự linh hoạt

Như bạn đã thấy trong phần trước, khi một trình trang trí sử dụng các đối số, bạn cần thêm một hàm bên ngoài bổ sung. Thử thách dành cho mã của bạn là tìm hiểu xem trình trang trí đã được gọi có hay không có đối số

Vì hàm để trang trí chỉ được truyền trực tiếp nếu trình trang trí được gọi mà không có đối số, nên hàm phải là một đối số tùy chọn. Điều này có nghĩa là tất cả các đối số trang trí phải được chỉ định bởi từ khóa. Bạn có thể thực thi điều này bằng cú pháp

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
066 đặc biệt, có nghĩa là tất cả các tham số sau đây chỉ dành cho từ khóa

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
85

Ở đây, đối số

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
067 đóng vai trò là điểm đánh dấu, lưu ý liệu trình trang trí có được gọi với đối số hay không

  1. Nếu
    >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    068 đã được gọi mà không có đối số, chức năng được trang trí sẽ được chuyển vào dưới dạng
    >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    067. Nếu nó đã được gọi với các đối số, thì
    >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    067 sẽ là
    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
    
    def say_whee[]:
        print["Whee!"]
    
    say_whee = my_decorator[say_whee]
    
    9 và một số đối số từ khóa có thể đã bị thay đổi so với giá trị mặc định của chúng.
    >>> def add_one[number]:
    ..     return number + 1
    
    >>> add_one[2]
    3
    
    066 trong danh sách đối số có nghĩa là các đối số còn lại không thể được gọi là đối số vị trí
  2. Trong trường hợp này, trình trang trí được gọi với các đối số. Trả về hàm trang trí có thể đọc và trả về hàm
  3. Trong trường hợp này, trình trang trí được gọi mà không có đối số. Áp dụng trình trang trí cho chức năng ngay lập tức

Sử dụng bản tóm tắt này trên trình trang trí

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
073 trong phần trước, bạn có thể viết như sau

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
86

So sánh điều này với bản gốc

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
073. Những thay đổi duy nhất là tham số
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
067 được thêm vào và
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
076-
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
077 ở cuối

Công thức 9. 6 của Sách dạy nấu ăn Python xuất sắc cho thấy một giải pháp thay thế bằng cách sử dụng

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
078

Những ví dụ này cho thấy rằng

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
073 hiện có thể được sử dụng có hoặc không có đối số

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
87

Nhớ lại rằng giá trị mặc định của

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
052 là 2

>>>

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
88

trang trí nhà nước

Đôi khi, thật hữu ích khi có một trình trang trí có thể theo dõi trạng thái. Ví dụ đơn giản, chúng ta sẽ tạo một decorator đếm số lần một hàm được gọi

Ghi chú. Ở phần đầu của hướng dẫn này, chúng ta đã nói về các hàm thuần túy trả về một giá trị dựa trên các đối số đã cho. Trình trang trí trạng thái hoàn toàn ngược lại, trong đó giá trị trả về sẽ phụ thuộc vào trạng thái hiện tại, cũng như các đối số đã cho

Trong phần tiếp theo, bạn sẽ thấy cách sử dụng các lớp để giữ trạng thái. Nhưng trong những trường hợp đơn giản, bạn cũng có thể sử dụng thuộc tính hàm

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
89

Trạng thái—số lần gọi hàm—được lưu trữ trong thuộc tính hàm

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
081 trên hàm bao bọc. Đây là tác dụng của việc sử dụng nó

>>>

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
20

Loại bỏ các quảng cáo

Các lớp học với tư cách là người trang trí

Cách điển hình để duy trì trạng thái là sử dụng các lớp. Trong phần này, bạn sẽ thấy cách viết lại ví dụ

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
082 từ phần trước bằng cách sử dụng một lớp làm công cụ trang trí

Nhớ lại rằng cú pháp trang trí

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
45 chỉ là một cách dễ dàng hơn để nói
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
084. Do đó, nếu
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
085 là một lớp, thì nó cần lấy
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
38 làm đối số trong phương thức
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
087 của nó. Hơn nữa, thể hiện của lớp cần phải có thể gọi được để nó có thể thay thế cho chức năng được trang trí

Để một thể hiện của lớp có thể gọi được, bạn triển khai phương thức đặc biệt

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
088

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
21

Phương thức

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
088 được thực thi mỗi khi bạn cố gắng gọi một thể hiện của lớp

>>>

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
22

Do đó, việc triển khai điển hình của lớp trang trí cần triển khai

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
087 và
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
088

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
23

Phương thức

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
087 phải lưu trữ tham chiếu đến hàm và có thể thực hiện bất kỳ khởi tạo cần thiết nào khác. Phương thức
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
088 sẽ được gọi thay vì chức năng được trang trí. Về cơ bản, nó thực hiện giống như hàm
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
33 trong các ví dụ trước đây của chúng tôi. Lưu ý rằng bạn cần sử dụng hàm
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
73 thay vì
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
68

Công cụ trang trí

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
097 này hoạt động giống như công cụ trang trí trong phần trước

>>>

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
20

Nhiều ví dụ trong thế giới thực hơn

Bây giờ chúng tôi đã đi một chặng đường dài, đã tìm ra cách tạo ra tất cả các loại trang trí. Hãy kết thúc nó, đưa kiến ​​thức mới tìm được của chúng ta vào việc tạo thêm một vài ví dụ có thể thực sự hữu ích trong thế giới thực

Làm chậm mã, xem lại

Như đã lưu ý trước đó, triển khai trước đây của chúng tôi về

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
94 luôn ngủ trong một giây. Bây giờ bạn đã biết cách thêm tham số vào trình trang trí, vì vậy, hãy viết lại
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
94 bằng cách sử dụng đối số
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
600 tùy chọn để kiểm soát thời gian ngủ của nó

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
25

Chúng tôi đang sử dụng bản soạn sẵn được giới thiệu trong phần Làm ơn cả hai, nhưng đừng bận tâm đến bánh mì để làm cho

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
94 có thể gọi được cả khi có và không có đối số. Chức năng đệ quy
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
96 tương tự như trước đó giờ ngủ hai giây giữa mỗi lần đếm

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
26

Như trước đây, bạn phải tự chạy ví dụ để xem tác dụng của trình trang trí

>>>

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
80

Tạo Singleton

Một singleton là một lớp chỉ có một thể hiện. Có một số singletons trong Python mà bạn sử dụng thường xuyên, bao gồm

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
9,
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
604 và
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
605. Thực tế là
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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
9 là một đơn vị cho phép bạn so sánh với
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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
9 bằng cách sử dụng từ khóa
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
608, như bạn đã thấy trong phần Làm ơn cả hai

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
28

Sử dụng

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
608 chỉ trả về
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
604 cho các đối tượng giống hệt nhau. Trình trang trí
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
036 sau đây biến một lớp thành một singleton bằng cách lưu trữ phiên bản đầu tiên của lớp dưới dạng một thuộc tính. Những lần thử tạo phiên bản sau này chỉ cần trả lại phiên bản đã lưu trữ

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
29

Như bạn thấy, trình trang trí lớp này theo cùng một khuôn mẫu như trình trang trí chức năng của chúng tôi. Sự khác biệt duy nhất là chúng tôi đang sử dụng

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
612 thay vì
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
38 làm tên tham số để chỉ ra rằng nó có nghĩa là trang trí lớp

Hãy xem nếu nó hoạt động

>>>

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
00

Có vẻ như rõ ràng rằng

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
614 thực sự là cùng một ví dụ với
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
615

Ghi chú. Các lớp Singleton không thực sự được sử dụng thường xuyên trong Python như trong các ngôn ngữ khác. Hiệu ứng của một singleton thường được triển khai tốt hơn dưới dạng một biến toàn cục trong một mô-đun

Giá trị trả về bộ đệm

Trình trang trí có thể cung cấp một cơ chế tốt để lưu vào bộ nhớ đệm và ghi nhớ. Ví dụ, hãy xem định nghĩa đệ quy của dãy Fibonacci

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
01

Mặc dù việc triển khai đơn giản nhưng hiệu suất thời gian chạy của nó rất tệ

>>>

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
02

Để tính số Fibonacci thứ mười, bạn thực sự chỉ cần tính các số Fibonacci trước đó, nhưng việc triển khai này bằng cách nào đó cần đến 177 phép tính. Nó trở nên tồi tệ hơn một cách nhanh chóng. 21891 tính toán là cần thiết cho

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
616 và gần 2. 7 triệu phép tính cho số thứ 30. Điều này là do mã tiếp tục tính toán lại các số Fibonacci đã biết

Giải pháp thông thường là triển khai các số Fibonacci bằng vòng lặp

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
617 và bảng tra cứu. Tuy nhiên, bộ nhớ đệm đơn giản của các tính toán cũng sẽ thực hiện thủ thuật

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
03

Bộ đệm hoạt động như một bảng tra cứu, do đó, bây giờ

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
618 chỉ thực hiện các phép tính cần thiết một lần

>>>

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
04

Lưu ý rằng trong cuộc gọi cuối cùng tới

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
619, không cần tính toán mới, vì số Fibonacci thứ tám đã được tính toán cho
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
620

Trong thư viện tiêu chuẩn, bộ đệm Ít được sử dụng gần đây nhất [LRU] có sẵn dưới dạng

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
621

Trình trang trí này có nhiều tính năng hơn tính năng bạn đã thấy ở trên. Bạn nên sử dụng

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
621 thay vì viết trình trang trí bộ đệm của riêng bạn

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
05

Tham số

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
623 chỉ định số lượng cuộc gọi gần đây được lưu vào bộ đệm. Giá trị mặc định là 128, nhưng bạn có thể chỉ định
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
624 để lưu trữ tất cả các lệnh gọi hàm. Tuy nhiên, hãy lưu ý rằng điều này có thể gây ra các vấn đề về bộ nhớ nếu bạn đang lưu vào bộ nhớ đệm nhiều đối tượng lớn

Bạn có thể sử dụng phương pháp

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
625 để xem bộ đệm hoạt động như thế nào và bạn có thể điều chỉnh nó nếu cần. Trong ví dụ của chúng tôi, chúng tôi đã sử dụng một
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
623 nhỏ giả tạo để xem ảnh hưởng của việc xóa các phần tử khỏi bộ đệm

>>>

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
06

Thêm thông tin về đơn vị

Ví dụ sau đây hơi giống với ví dụ Đăng ký plugin trước đó, ở chỗ nó không thực sự thay đổi hành vi của chức năng được trang trí. Thay vào đó, nó chỉ cần thêm

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
627 làm thuộc tính chức năng

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
07

Ví dụ sau tính toán thể tích của một hình trụ dựa trên bán kính và chiều cao của nó tính bằng centimet

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
08

Thuộc tính chức năng

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
628 này sau này có thể được truy cập khi cần

>>>

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
09

Lưu ý rằng bạn có thể đã đạt được điều gì đó tương tự bằng cách sử dụng chú thích chức năng

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
0

Tuy nhiên, vì các chú thích được sử dụng cho các gợi ý kiểu nên sẽ khó kết hợp các đơn vị như chú thích với kiểm tra kiểu tĩnh

Các đơn vị thậm chí còn trở nên mạnh mẽ và thú vị hơn khi được kết nối với thư viện có thể chuyển đổi giữa các đơn vị. Một thư viện như vậy là

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
629. Với
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
629 được cài đặt [
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
631], chẳng hạn, bạn có thể chuyển đổi âm lượng thành inch khối hoặc gallon

>>>

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
1

Bạn cũng có thể sửa đổi trình trang trí để trả về trực tiếp một

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
629
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
633. Một
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
633 như vậy được tạo bằng cách nhân một giá trị với đơn vị. Trong
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
629, các đơn vị phải được tra cứu trong một
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
636. Sổ đăng ký được lưu trữ dưới dạng thuộc tính chức năng để tránh làm lộn xộn không gian tên

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
2

Với trình trang trí

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
637, việc chuyển đổi các đơn vị thực tế rất dễ dàng

>>>

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
3

Xác thực JSON

Hãy xem xét một trường hợp sử dụng cuối cùng. Hãy xem nhanh trình xử lý tuyến đường Flask sau đây

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
4

Ở đây chúng tôi đảm bảo rằng khóa

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
638 là một phần của yêu cầu. Mặc dù xác thực này hoạt động, nhưng nó thực sự không thuộc về chức năng đó. Ngoài ra, có lẽ có những tuyến đường khác sử dụng xác thực chính xác như vậy. Vì vậy, hãy để nó KHÔ và trừu tượng hóa mọi logic không cần thiết bằng một trình trang trí. Người trang trí
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
639 sau đây sẽ thực hiện công việc

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
5

Trong đoạn mã trên, trình trang trí lấy một danh sách có độ dài thay đổi làm đối số để chúng ta có thể chuyển bao nhiêu đối số chuỗi nếu cần, mỗi đối số đại diện cho một khóa được sử dụng để xác thực dữ liệu JSON

  1. Danh sách các khóa phải có trong JSON được đưa ra làm đối số cho trình trang trí
  2. Hàm bao bọc xác thực rằng mỗi khóa được mong đợi đều có trong dữ liệu JSON

Sau đó, trình xử lý định tuyến có thể tập trung vào công việc thực sự của nó—cập nhật điểm—vì nó có thể cho rằng dữ liệu JSON là hợp lệ một cách an toàn

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

def say_whee[]:
    print["Whee!"]

say_whee = my_decorator[say_whee]
6

Phần kết luận

Đây là một hành trình khá. Bạn đã bắt đầu hướng dẫn này bằng cách tìm hiểu kỹ hơn một chút về các hàm, đặc biệt là cách chúng có thể được định nghĩa bên trong các hàm khác và được truyền xung quanh giống như bất kỳ đối tượng Python nào khác. Sau đó, bạn đã học về các bộ trang trí và cách viết chúng sao cho

  • Chúng có thể được tái sử dụng
  • Họ có thể trang trí các chức năng với các đối số và giá trị trả về
  • Họ có thể sử dụng
    def say_hello[name]:
        return f"Hello {name}"
    
    def be_awesome[name]:
        return f"Yo {name}, together we are the awesomest!"
    
    def greet_bob[greeter_func]:
        return greeter_func["Bob"]
    
    68 để trông giống chức năng được trang trí hơn

Trong phần thứ hai của hướng dẫn, bạn đã thấy các trình trang trí nâng cao hơn và học cách

  • Trang trí lớp học
  • Trang trí tổ
  • Thêm đối số vào trang trí
  • Giữ trạng thái trong trang trí
  • Sử dụng các lớp làm trang trí

Bạn đã thấy rằng, để xác định một trình trang trí, bạn thường xác định một hàm trả về một hàm bao bọc. Hàm bao bọc sử dụng

def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
55 và
def say_hello[name]:
    return f"Hello {name}"

def be_awesome[name]:
    return f"Yo {name}, together we are the awesomest!"

def greet_bob[greeter_func]:
    return greeter_func["Bob"]
56 để truyền đối số cho hàm được trang trí. Nếu bạn muốn trình trang trí của mình cũng nhận các đối số, bạn cần lồng hàm bao bọc bên trong một hàm khác. Trong trường hợp này, bạn thường kết thúc với ba câu lệnh
>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
643

Bạn có thể tìm mã từ hướng dẫn này trực tuyến

Đọc thêm

Nếu bạn vẫn đang tìm kiếm thêm, cuốn sách Thủ thuật Python của chúng tôi có một phần về trang trí, cũng như Sách dạy nấu ăn Python của David Beazley và Brian K. Jones

Để tìm hiểu sâu về cuộc thảo luận lịch sử về cách triển khai trình trang trí trong Python, hãy xem PEP 318 cũng như Wiki trang trí Python. Có thể tìm thấy nhiều ví dụ hơn về trình trang trí trong Thư viện trình trang trí Python. Mô-đun

>>> def add_one[number]:
..     return number + 1

>>> add_one[2]
3
644 có thể đơn giản hóa việc tạo trình trang trí của riêng bạn và tài liệu của nó chứa các ví dụ về trình trang trí khác

Ngoài ra, chúng tôi đã tập hợp một bảng lừa đảo trang trí Python ngắn và hấp dẫn dành cho bạn

Trang trí Cheat Sheet. Nhấp vào đây để có quyền truy cập vào bảng lừa đảo trang trí Python ba trang miễn phí tóm tắt các kỹ thuật được giải thích trong hướng dẫn này

Đánh dấu là đã hoàn thành

Xem ngay Hướng dẫn này có một khóa học video liên quan do nhóm Real Python tạo. Xem nó cùng với hướng dẫn bằng văn bản để hiểu sâu hơn. Trang trí Python 101

🐍 Thủ thuật Python 💌

Nhận một Thủ thuật Python ngắn và hấp dẫn được gửi đến hộp thư đến của bạn vài ngày một lần. Không có thư rác bao giờ. Hủy đăng ký bất cứ lúc nào. Được quản lý bởi nhóm Real Python

Gửi cho tôi thủ thuật Python »

Giới thiệu về Geir Arne Hjelle

Geir Arne là một Pythonista cuồng nhiệt và là thành viên của nhóm hướng dẫn Real Python

» Thông tin thêm về Geir Arne

Mỗi hướng dẫn tại Real Python được tạo bởi một nhóm các nhà phát triển để nó đáp ứng các tiêu chuẩn chất lượng cao của chúng tôi. Các thành viên trong nhóm đã làm việc trong hướng dẫn này là

Aldren

Brad

Đan

Joanna

Michael

Bậc thầy Kỹ năng Python trong thế giới thực Với quyền truy cập không giới hạn vào Python thực

Tham gia với chúng tôi và có quyền truy cập vào hàng nghìn hướng dẫn, khóa học video thực hành và cộng đồng các Pythonistas chuyên gia

Nâng cao kỹ năng Python của bạn »

Bậc thầy Kỹ năng Python trong thế giới thực
Với quyền truy cập không giới hạn vào Python thực

Tham gia với chúng tôi và có quyền truy cập vào hàng ngàn hướng dẫn, khóa học video thực hành và cộng đồng Pythonistas chuyên gia

Nâng cao kỹ năng Python của bạn »

Bạn nghĩ sao?

Đánh giá bài viết này

Tweet Chia sẻ Chia sẻ Email

Bài học số 1 hoặc điều yêu thích mà bạn đã học được là gì?

Mẹo bình luận. Những nhận xét hữu ích nhất là những nhận xét được viết với mục đích học hỏi hoặc giúp đỡ các sinh viên khác. Nhận các mẹo để đặt câu hỏi hay và nhận câu trả lời cho các câu hỏi phổ biến trong cổng thông tin hỗ trợ của chúng tôi

Chủ Đề