Hướng dẫn what is decorator in python class? - decorator trong lớp python là gì?
Xem bây giờ hướng dẫn này có một khóa học video liên quan được tạo bởi nhóm Python thực sự. Xem nó cùng với hướng dẫn bằng văn bản để làm sâu sắc thêm sự hiểu biết của bạn: Người trang trí Python 101 This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Python Decorators 101 Show
Trong hướng dẫn này về các nhà trang trí, chúng tôi sẽ xem xét chúng là gì và cách tạo và sử dụng chúng. Các nhà trang trí cung cấp một cú pháp đơn giản để gọi các chức năng bậc cao. Theo định nghĩa, một bộ trang trí là một hàm có một chức năng khác và mở rộng hành vi của hàm sau mà không sửa đổi rõ ràng nó. Điều này nghe có vẻ khó hiểu, nhưng nó thực sự không, đặc biệt là sau khi bạn đã thấy một vài ví dụ về cách các nhà trang trí hoạt động. Bạn có thể tìm thấy tất cả các ví dụ từ bài viết này ở đây. Updates:
Chức năngTrước khi bạn có thể hiểu các nhà trang trí, trước tiên bạn phải hiểu cách thức hoạt động của các chức năng. Đố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:a function returns a value based on the given arguments. Here is a very simple example: >>>
Nói chung, các chức năng 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 7 là một ví dụ cơ bản về điều này: nó trả về 8 trong khi có tác dụng phụ của việc xuất ra thứ gì đó vào bảng điều khiển. Tuy nhiên, để hiểu các nhà trang trí, nó đủ để suy nghĩ về các chức năng như một cái gì đó biến các lập luận được đưa ra thành một giá trị.Đối tượng hạng nhấtTrong Python, các chức năng là các đối tượng hạng nhất. Điều này có nghĩa là các chức năng 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.). Xem xét ba chức năng sau:functions can be passed around and used as arguments, just like any other object (string, int, float, list, and so on). Consider the following three functions:
Ở đây, 9 và 00 là các chức năng thường xuyên mong đợi một tên được đặt dưới dạng chuỗi. Tuy nhiên, hàm 01 mong đợi một chức năng như đối số của nó. Ví dụ, chúng ta có thể chuyển nó cho chức năng 9 hoặc 00:>>> Nói chung, các chức năng 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 7 là một ví dụ cơ bản về điều này: nó trả về 8 trong khi có tác dụng phụ của việc xuất ra thứ gì đó vào bảng điều khiển. Tuy nhiên, để hiểu các nhà trang trí, nó đủ để suy nghĩ về các chức năng như một cái gì đó biến các lập luận được đưa ra thành một giá trị.Đối tượng hạng nhất Trong Python, các chức năng là các đối tượng hạng nhất. Điều này có nghĩa là các chức năng 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.). Xem xét ba chức năng sau:Ở đây, 9 và 00 là các chức năng thường xuyên mong đợi một tên được đặt dưới dạng chuỗi. Tuy nhiên, hàm 01 mong đợi một chức năng như đối số của nó. Ví dụ, chúng ta có thể chuyển nó cho chức năng 9 hoặc 00:
>>>
Nói chung, các chức năng 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 7 là một ví dụ cơ bản về điều này: nó trả về 8 trong khi có tác dụng phụ của việc xuất ra thứ gì đó vào bảng điều khiển. Tuy nhiên, để hiểu các nhà trang trí, nó đủ để suy nghĩ về các chức năng như một cái gì đó biến các lập luận được đưa ra thành một giá trị.Đối tượng hạng nhất
Trong Python, các chức năng là các đối tượng hạng nhất. Điều này có nghĩa là các chức năng 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.). Xem xét ba chức năng 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) 9 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") 00 là các chức năng thường xuyên mong đợi một 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") 01 mong đợi một chức năng như đối số của nó. Ví dụ, chúng ta có thể chuyển nó cho 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) 9 hoặ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") 00:
Lưu ý rằng 04 đề cập đến hai chức năng, nhưng theo những cách khác nhau: 01 và 06. Hàm 06 được đặt tên mà không có dấu ngoặc đơn. Điều này có nghĩa là chỉ có một tham chiếu đến hàm được thông qua. Hàm không được thực thi. Hàm 01, mặt khác, được viết bằng dấu ngoặc đơn, vì vậy nó sẽ được gọi như bình thường.returning a reference to the function 18. In
contrast 12 with parentheses refers to the result of evaluating the function. This can be seen in the following example:>>>
Nói chung, các chức năng 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 7 là một ví dụ cơ bản về điều này: nó trả về 8 trong khi có tác dụng phụ của việc xuất ra thứ gì đó vào bảng điều khiển. Tuy nhiên, để hiểu các nhà trang trí, nó đủ để suy nghĩ về các chức năng như một cái gì đó biến các lập luận được đưa ra thành một giá trị.Đối tượng hạng nhất >>>
Nói chung, các chức năng 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 7 là một ví dụ cơ bản về điều này: nó trả về 8 trong khi có tác dụng phụ của việc xuất ra thứ gì đó vào bảng điều khiển. Tuy nhiên, để hiểu các nhà trang trí, nó đủ để suy nghĩ về các chức năng như một cái gì đó biến các lập luận được đưa ra thành một giá trị.Đối tượng hạng nhấtTrong Python, các chức năng là các đối tượng hạng nhất. Điều này có nghĩa là các chức năng 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.). Xem xét ba chức năng sau:
Bạn có thể đoán điều gì xảy ra khi bạn gọi 30 không? Thử nó:>>> 0Để hiểu những gì diễn ra ở đây, hãy nhìn 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 cho đến nay. Cái gọi là trang trí xảy ra ở dòng sau: 1Trong thực tế, tên 31 hiện chỉ vào hàm bên trong 32. Hãy nhớ rằng bạn trả về 33 như một hàm khi bạn gọi 34:>>> 2Để hiểu những gì diễn ra ở đây, hãy nhìn 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 cho đến nay. Cái gọi là trang trí xảy ra ở dòng sau:decorators wrap a function, modifying its behavior. Trong thực tế, tên 31 hiện chỉ vào hàm bên trong 32. Hãy nhớ rằng bạn trả về 33 như một hàm khi bạn gọi 34: 3Tuy nhiên, 32 có tham chiếu đến 30 gốc là 37 và các cuộc gọi chức năng đó giữa hai cuộc gọi đến 7.Đặt đơn giản: Người trang trí bọc một chức năng, sửa đổi hành vi của nó.Trước khi tiếp tục, hãy để một cái nhìn vào một ví dụ thứ hai. Bởi vì 32 là một hàm Python thông thường, cách một người trang trí sửa đổi một hàm có thể thay đổi một cách linh hoạt. Vì vậy, để không làm phiền hàng xóm của bạn, ví dụ sau đây sẽ chỉ chạy mã được trang trí trong ngày:Nếu bạn cố gắng gọi 30 sau giờ đi ngủ, sẽ không có gì xảy ra:use decorators in a simpler way with the 43 symbol, sometimes called the “pie” syntax. The following example does the exact same thing as the first decorator example: 4Cú 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") 30 ở trên là một chút cồng kềnh. Trước hết, cuối cùng bạn 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") 31 ba lần. Ngoài ra, trang trí bị ẩn một chút bên dưới định nghĩa của hàm.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 biểu tượng 43, đôi khi được gọi là cú pháp của Pie Pie. 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:Vì vậy, 44 chỉ là một cách nói dễ dàng hơn 45. Nó cách bạn áp dụng một người trang trí vào một chức năng. 5Tái sử dụng trang trí 6Hãy nhớ lại rằng một người trang trí chỉ là một chức năng 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 có sẵn. Hãy để di chuyển bộ trang trí đến mô -đun riêng có thể được sử dụng trong nhiều chức năng khác. >>> Tạo một tệp được gọi là 46 với nội dung sau: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:Khi bạn chạy ví dụ này, bạn sẽ thấy rằng 30 ban đầu được thực thi hai lần: 8 7>>> 9Chức năng trang trí với các đối số Nói rằng bạn có một chức năng chấp nhận một số đối số. Bạn vẫn có thể trang trí nó? Hãy thử thử: 0Thật không may, việc chạy mã này sẽ gây ra lỗi: >>> 1Vấ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") 48 không có 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") 49 đã được truyền cho nó. Bạn có thể khắc phục điều này bằng cách để 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") 48 chấp nhận một đối số, nhưng sau đó nó sẽ không hoạt động cho 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") 30 mà bạn đã tạo trước đó.Giải pháp là sử dụng 52 và 53 trong hàm trình bao bọc bên trong. Sau đó, nó sẽ chấp nhận một số lượng tùy ý của các đối số vị trí và từ khóa. Viết lại 46 như sau: 2Hàm bên trong 48 hiện chấp nhận bất kỳ số lượng đối số nào và truyền chúng vào chức năng mà nó trang trí. Bây giờ cả ví dụ 30 và 57 của bạn đều hoạt động:>>> 3Trả lại 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ả lại của các chức năng được trang trí? Chà, đó là cách trang trí để quyết định. Hãy nói rằng bạn trang trí một chức năng đơn giản như sau: Cố gắng sử dụng nó:make sure the wrapper function returns the return value of the decorated function. Change your 46 file: 4Rất tiếc, người trang trí của bạn đã ăn giá trị trả lại từ hàm. >>> 5Bở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") 58 không trả lại một cách rõ ràng một giá trị, 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") 59 đã kết thúc trở 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) 8.Để khắc phục điều này, bạn cần đảm bảo hàm trình bao bọc trả về giá trị trả về của hàm được trang trí. Thay đổi tệp 46 của bạn:>>> 6Giá trị trả về từ lần thực hiện cuối cùng của hàm được trả về: >>> 7Bạn là ai, thực sự? Một sự tiện lợi tuyệt vời khi làm việc với Python, đặc biệt là trong vỏ tương tác, là khả năng nội tâm mạnh mẽ của nó. Hướng nội 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ó: 8Sự hướng nội cũng hoạt động cho các chức năng mà bạn cũng tự xác định: >>> 9Tuy nhiên, sau khi được trang trí, 30 đã rất bối rối về bản sắc của nó. Bây giờ nó báo cáo là hàm bên trong 48 bên trong trình trang trí 64. Mặc dù về mặt kỹ thuật, điều nà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 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") 65, sẽ lưu giữ thông tin về chức năng ban đầu. Cập nhậ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") 46 một lần nữa:Bạn không cần phải thay đổi bất cứ điều gì về chức năng 30 được trang trí: 0Công thức này là một mẫu nồi hơi tốt để xây dựng các nhà trang trí phức tạp hơn. Chức năng thời gianHãy bắt đầu bằng cách tạo ra một nhà trang trí 69. Nó sẽ đo thời gian một hàm cần thực hiện và in thời lượng vào bảng điều khiển. Đây là mã: 1Bộ trang trí này hoạt động bằng cách lưu trữ thời gian ngay trước khi hàm bắt đầu chạy (tại dòng được đánh dấu 70) và ngay sau khi chức năng kết thúc (tại 71). Thời gian hàm mất sau đó là sự khác biệt giữa hai (tại 72). Chúng tôi sử dụng hàm 73, công việc tốt là đo khoảng thời gian. Dưới đây là một số ví dụ về thời gian:>>> 2Tự mình điều hành. Làm việc thông qua dòng mã từng dòng. Hãy chắc chắn rằng bạn hiểu cách nó hoạt động. Mặc dù vậy, đừng lo lắng nếu bạn không nhận được nó. Trang trí là những sinh vật tiên tiến. Cố gắng ngủ trên nó hoặc tạo ra một bản vẽ của dòng chảy. Mã gỡ lỗiTrình trang trí 74 sau đây sẽ in các đối số Một hàm được gọi cũng như giá trị trả về của nó mỗi khi hàm được gọi: 3Chữ ký được tạo bằng cách tham gia 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 đây tương ứng với các nhận xét được đánh số trong mã:
Hãy cùng xem cách thức trang trí hoạt động trong thực tế bằng cách áp dụng nó vào một chức năng đơn giản với một vị trí và một đối số từ khóa: 4Lưu ý cách trình trang trí 74 in chữ ký và giá trị trả về của hàm 80:>>> 5Tự mình điều hành. Làm việc thông qua dòng mã từng dòng. Hãy chắc chắn rằng bạn hiểu cách nó hoạt động. Mặc dù vậy, đừng lo lắng nếu bạn không nhận được nó. Trang trí là những sinh vật tiên tiến. Cố gắng ngủ trên nó hoặc tạo ra một bản vẽ của dòng chảy. Mã gỡ lỗi 6Trình trang trí 74 sau đây sẽ in các đối số Một hàm được gọi cũng như giá trị trả về của nó mỗi khi hàm được gọi:Chữ ký được tạo bằng cách tham gia 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 đây tương ứng với các nhận xét được đánh số trong mã: >>> 7Tự mình điều hành. Làm việc thông qua dòng mã từng dòng. Hãy chắc chắn rằng bạn hiểu cách nó hoạt động. Mặc dù vậy, đừng lo lắng nếu bạn không nhận được nó. Trang trí là những sinh vật tiên tiến. Cố gắng ngủ trên nó hoặc tạo ra một bản vẽ của dòng chảy. Mã gỡ lỗiTrình trang trí 74 sau đây sẽ in các đối số Một hàm được gọi cũng như giá trị trả về của nó mỗi khi hàm được gọi: 8Chữ ký được tạo bằng cách tham gia 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 đây tương ứng với các nhận xét được đánh số trong mã: >>> 9Tự mình điều hành. Làm việc thông qua dòng mã từng dòng. Hãy chắc chắn rằng bạn hiểu cách nó hoạt động. Mặc dù vậy, đừng lo lắng nếu bạn không nhận được nó. Trang trí là những sinh vật tiên tiến. Cố gắng ngủ trên nó hoặc tạo ra một bản vẽ của dòng chảy. Mã gỡ lỗiTrình trang trí 74 sau đây sẽ in các đối số Một hàm được gọi cũng như giá trị trả về của nó mỗi khi hàm được gọi: 0Chữ ký được tạo bằng cách tham gia 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 đây tương ứng với các nhận xét được đánh số trong mã: Tạo một danh sách các đối số vị trí. Sử dụng 75 để có được một chuỗi đẹp đại diện cho mỗi đối số.>>> 1Tự mình điều hành. Làm việc thông qua dòng mã từng dòng. Hãy chắc chắn rằng bạn hiểu cách nó hoạt động. Mặc dù vậy, đừng lo lắng nếu bạn không nhận được nó. Trang trí là những sinh vật tiên tiến. Cố gắng ngủ trên nó hoặc tạo ra một bản vẽ của dòng chảy. Mã gỡ lỗi >>> 2Tự mình điều hành. Làm việc thông qua dòng mã từng dòng. Hãy chắc chắn rằng bạn hiểu cách nó hoạt động. Mặc dù vậy, đừng lo lắng nếu bạn không nhận được nó. Trang trí là những sinh vật tiên tiến. Cố gắng ngủ trên nó hoặc tạo ra một bản vẽ của dòng chảy. Người dùng đã đăng nhập?Ví dụ cuối cùng trước khi chuyển sang một số nhà trang trí fancier 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 bình để thiết lập trang web 97 chỉ hiển thị cho người dùng đã đăng nhập hoặc xác thực khác: 3Mặc dù điều này đưa ra một ý tưởng về cách thêm xác thực vào khung web của bạn, nhưng bạn thường không nên tự viết các loại 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 bảo mật và chức năng. Trang trí lạ mắtCho đến nay, bạn đã thấy cách tạo ra các nhà trang trí đơn giản. Bạn đã có một sự hiểu biết khá tốt về những người trang trí là gì và cách họ làm việc. Hãy nghỉ ngơi từ bài viết này để thực hành mọi thứ bạn đã học được. Trong phần thứ hai của hướng dẫn này, chúng tôi sẽ khám phá các tính năng nâng cao hơn, bao gồm cả cách sử dụng như sau:
Lớp trang tríCó hai cách khác nhau bạn có thể sử dụng trang trí trên các lớp học. Cái đầu tiên rất gần với những gì bạn đã thực hiện với các chức năng: bạn có thể trang trí các phương pháp của một lớp. Đây là một trong những động lực để giới thiệu các nhà trang trí trở lại trong ngày.decorate the methods of a class. This was one of the motivations for introducing decorators back in the day. Một số nhà trang trí thường được sử dụng thậm chí còn được xây dựng trong Python là 98, 99 và 00. Các nhà trang trí 98 và 99 đượ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 trường hợp cụ thể của lớp đó. Bộ trang trí 00 đượ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 dưới đây cho một ví dụ sử dụng các trang trí này.Định nghĩa sau đây của lớp 04 sử dụng các nhà trang trí 98, 99 và 00: 4Trong lớp học này:
Ví dụ, lớp 04 có thể được sử dụng như sau:>>> 5Hãy để xác định một lớp trong đó chúng tôi trang trí một số phương pháp của nó bằng cách sử dụng các nhà trang trí 74 và 69 từ trước đó: 6Sử dụng lớp này, bạn có thể thấy hiệu ứng của các nhà trang trí: >>> 7Hãy để xác định một lớp trong đó chúng tôi trang trí một số phương pháp của nó bằng cách sử dụng các nhà trang trí 74 và 69 từ trước đó:decorate the whole class. This is, for example, done in the new 19 module in Python 3.7: 8Sử dụng lớp này, bạn có thể thấy hiệu ứng của các nhà trang trí: Cách khác để sử dụng các nhà trang trí trên các lớp học là trang trí cho cả lớp. Đây là, ví dụ, được thực hiện trong mô -đun 19 mới trong Python 3.7:Ý 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ể đã thực hiện trang trí bằng cách viết 20. 9Một cách sử dụng phổ biến của các nhà trang trí lớp là là một sự thay thế đơn giản hơn cho một số trường hợp sử dụng của các metaclass. 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 người trang trí lớp học rất giống với việc viết một bộ trang trí chức năng. Sự khác biệt duy nhất là người trang trí sẽ nhận được một lớp và không phải là một chức năng như một đối số. Trong thực tế, tất cả các nhà trang trí bạn thấy ở trên sẽ hoạt động như những người trang trí lớp học. Khi bạn đang sử dụng chúng trên một lớp thay vì một hàm, hiệu ứng của chúng có thể không phải là thứ bạn muốn. Trong ví dụ sau, bộ trang trí 69 được áp dụng cho một lớp:>>> 0Hãy để xác định một lớp trong đó chúng tôi trang trí một số phương pháp của nó bằng cách sử dụng các nhà trang trí 74 và 69 từ trước đó:
Sử dụng lớp này, bạn có thể thấy hiệu ứng của các nhà trang trí:Cách khác để sử dụng các nhà trang trí trên các lớp học là trang trí cho cả lớp. Đây là, ví dụ, được thực hiện trong mô -đun 19 mới trong Python 3.7:apply several decorators to a function by stacking them on top of each other: 1Ý 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ể đã thực hiện trang trí bằng cách viết 20.>>> 2Quan sát sự khác biệt nếu chúng ta thay đổi thứ tự 74 và 27: 3Trong trường hợp này, 27 cũng sẽ được áp dụng cho 74:>>> 4Trang trí với lập luậnĐôi khi, nó rất hữu ích để chuyển các đối số cho các nhà trang trí của bạn. Ví dụ, 27 có thể được mở rộng cho một công cụ trang trí 35. Số lần để thực hiện hàm được trang trí sau đó có thể được đưa ra như một đối số.pass arguments to your decorators. For instance, 27 could be extended to a 35 decorator. The number of times to execute the decorated function could then be given as an argument.Điều này sẽ cho phép bạn làm một cái gì đó như thế này: 5>>> 6Hã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 43 đã đề cập đến một đối tượng hàm có thể được gọi với một hàm khác. Để nhất quán, sau đó bạn cần 37 để trả về một đối tượng chức năng có thể hoạt động như một người trang trí. May mắn thay, bạn đã biết cách trả lại các chức năng! Nói chung, bạn muốn một cái gì đó như sau: 7Thông thường, bộ trang trí tạo và trả về hàm trình bao bọc bên trong, vì vậy viết ví dụ đầy đủ sẽ cung cấp cho bạn một hàm bên trong 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 một khoảnh khắc: 8Trông có vẻ hơi lộn xộn, nhưng chúng tôi chỉ đặt cùng một mẫu trang trí mà bạn đã thấy nhiều lần bây giờ trong một 38 bổ sung xử lý các đối số cho người trang trí. Hãy bắt đầu với chức năng trong cùng: 9Hàm 39 này có các đối số tùy ý và trả về giá trị của hàm được trang trí, 40. Hàm trình bao bọc này cũng chứa vòng lặp gọi hàm được trang trí 41 lần. Điều này không khác với các hàm trình bao bọc trước đó mà bạn đã thấy, ngoại trừ việc nó đang sử dụng tham số 41 phải được cung cấp từ bên ngoài.Một bước ra, bạn sẽ tìm thấy chức năng trang trí: 0Một lần nữa, 43 trông giống hệt như các chức năng trang trí mà bạn đã viết trước đó, ngoại trừ việc nó có tên khác nhau. Điều đó bởi vì chúng tôi bảo lưu tên cơ sở.Như bạn đã thấy, hàm ngoài cùng trả về một tham chiếu đến hàm trang trí: 1Có một vài điều tinh tế xảy ra trong hàm 44:
Với mọi thứ được thiết lập, hãy để xem kết quả có phải là dự kiến không: 5>>> 6Chỉ là kết quả chúng tôi đã nhắm đến. Cả hai làm ơn, nhưng đừng bận tâm đến bánh mìVới một chút quan tâm, bạn cũng có thể xác định các nhà trang trí có thể được sử dụng cả có và không có tranh luận. Nhiều khả năng, bạn không cần điều này, nhưng thật tuyệt khi có sự linh hoạt.decorators that can be used both with and without arguments. Most likely, you don’t need this, but it is nice to have the flexibility. Như bạn đã thấy trong phần trước, khi một người trang trí sử dụng các đối số, bạn cần thêm một hàm bên ngoài. Thách thức là mã của bạn để tìm ra nếu người trang trí đã được gọi có hoặc không có tranh luận. Vì chức năng trang trí chỉ được truyền trực tiếp nếu người trang trí được gọi mà không có đối số, chức năng 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ằng từ khóa. Bạn có thể thực thi điều này với cú pháp 55 đặc biệt, điều đó có nghĩa là tất cả các tham số sau đây chỉ dành cho từ khóa: 4Ở đây, lập luận 56 hoạt động như một điểm đánh dấu, lưu ý liệu người trang trí có được gọi với các đối số hay không:
Sử dụng bảng hơi này trên trình trang trí 62 trong phần trước, bạn có thể viết như sau: 5So sánh điều này với 62 ban đầu. Các thay đổi duy nhất là tham số 56 được thêm vào và ________ 265 -____ ____ 266 ở cuối.Công thức 9.6 của cuốn sách nấu ăn Python tuyệt vời cho thấy một giải pháp thay thế sử dụng 67.Các ví dụ này cho thấy 62 hiện có thể được sử dụng có hoặc không có đối số: 6Hãy nhớ lại rằng giá trị mặc định của 41 là 2:>>> 7Trang trí trạng tháiĐôi khi, nó rất hữu ích để có một người trang trí có thể theo dõi trạng thái. Ví dụ đơn giản, chúng tôi sẽ tạo một bộ trang trí đếm số lần một hàm được gọi là.a decorator that can keep track of state. As a simple example, we will create a decorator that counts the number of times a function is called. 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 các trường hợp đơn giản, bạn cũng có thể thoát khỏi việc sử dụng các thuộc tính chức năng: 8Trạng thái, số lượng các cuộc gọi đến hàm, được lưu trữ trong thuộc tính hàm 70 trên hàm trình bao bọc. Đây là hiệu ứng của việc sử dụng nó:>>> 9Trang trí trạng tháiĐôi khi, nó rất hữu ích để có một người trang trí có thể theo dõi trạng thái. Ví dụ đơn giản, chúng tôi sẽ tạo một bộ trang trí đếm số lần một hàm được gọi là.using a class as a decorator. 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 các trường hợp đơn giản, bạn cũng có thể thoát khỏi việc sử dụng các thuộc tính chức năng: Trạng thái, số lượng các cuộc gọi đến hàm, được lưu trữ trong thuộc tính hàm 70 trên hàm trình bao bọc. Đây là hiệu ứng của việc sử dụng nó: 0Các lớp học như người trang trí >>> 1Trang trí trạng thái 2Đôi khi, nó rất hữu ích để có một người trang trí có thể theo dõi trạng thái. Ví dụ đơn giản, chúng tôi sẽ tạo một bộ trang trí đếm số lần một hàm được gọi là. 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 các trường hợp đơn giản, bạn cũng có thể thoát khỏi việc sử dụng các thuộc tính chức năng: >>> 9Trang trí trạng tháiĐôi khi, nó rất hữu ích để có một người trang trí có thể theo dõi trạng thái. Ví dụ đơn giản, chúng tôi sẽ tạo một bộ trang trí đếm số lần một hàm được gọi là. 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 các trường hợp đơn giản, bạn cũng có thể thoát khỏi việc sử dụng các thuộc tính chức năng:Trạng thái, số lượng các cuộc gọi đến hàm, được lưu trữ trong thuộc tính hàm 70 trên hàm trình bao bọc. Đây là hiệu ứng của việc sử dụng nó: 4Các lớp học như người trang trí 5Cách điển hình để duy trì trạng thái là bằng cách 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ụ 71 từ phần trước bằng cách sử dụng một lớp làm người trang trí.>>> 9Trang trí trạng tháiĐôi khi, nó rất hữu ích để có một người trang trí có thể theo dõi trạng thái. Ví dụ đơn giản, chúng tôi sẽ tạo một bộ trang trí đếm số lần một hàm được gọi là. 7Trong 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 các trường hợp đơn giản, bạn cũng có thể thoát khỏi việc sử dụng các thuộc tính chức năng: 8Trạng thái, số lượng các cuộc gọi đến hàm, được lưu trữ trong thuộc tính hàm 70 trên hàm trình bao bọc. Đây là hiệu ứng của việc sử dụng nó:Các lớp học như người trang trí >>> 9Trang trí trạng thái Đôi khi, nó rất hữu ích để có một người trang trí có thể theo dõi trạng thái. Ví dụ đơn giản, chúng tôi sẽ tạo một bộ trang trí đếm số lần một hàm được gọi là.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 các trường hợp đơn giản, bạn cũng có thể thoát khỏi việc sử dụng các thuộc tính chức năng: 0Trạng thái, số lượng các cuộc gọi đến hàm, được lưu trữ trong thuộc tính hàm 70 trên hàm trình bao bọc. Đây là hiệu ứng của việc sử dụng nó:>>> 1Các lớp học như người trang trí Giải pháp thông thường là triển khai các số Fibonacci bằng cách sử dụng vòng lặp 06 và bảng tra cứu. Tuy nhiên, bộ đệm đơn giản của các tính toán cũng sẽ thực hiện thủ thuật: 2Bộ đệm hoạt động như một bảng tra cứu, vì vậy bây giờ 07 chỉ thực hiện các tính toán cần thiết một lần:>>> 3Lưu ý rằng trong cuộc gọi cuối cùng tới 08, không cần tính toán mới, vì số Fibonacci thứ tám đã được tính toán cho 09.Trong thư viện tiêu chuẩn, bộ đệm được sử dụng gần đây nhất (LRU) có sẵn dưới dạng 10.Trang trí này có nhiều tính năng hơn so với cái bạn thấy ở trên. Bạn nên sử dụng 10 thay vì viết bộ trang trí bộ nhớ cache của riêng mình: 4Tham số 12 chỉ định có bao nhiêu cuộc gọi gần đây được lưu trong bộ nhớ cache. Giá trị mặc định là 128, nhưng bạn có thể chỉ định 13 để lưu trữ tất cả các cuộc gọi chức năng. Tuy nhiên, hãy lưu ý rằng điều này có thể gây ra sự cố bộ nhớ nếu bạn đang lưu trữ nhiều đối tượng lớn.Bạn có thể sử dụng phương thức 14 để 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 12 nhỏ nhân tạo để xem ảnh hưởng của các yếu tố bị xóa khỏi bộ đệm:>>> 5Lưu ý rằng trong cuộc gọi cuối cùng tới def parent(): print("Printing from the parent() function") def first_child(): print("Printing from the first_child() function") def second_child(): print("Printing from the second_child() function") second_child() first_child() 08, không cần tính toán mới, vì số Fibonacci thứ tám đã được tính toán cho def parent(): print("Printing from the parent() function") def first_child(): print("Printing from the first_child() function") def second_child(): print("Printing from the second_child() function") second_child() first_child() 09.Trong thư viện tiêu chuẩn, bộ đệm được sử dụng gần đây nhất (LRU) có sẵn dưới dạng 10. 6Trang trí này có nhiều tính năng hơn so với cái bạn thấy ở trên. Bạn nên sử dụng 10 thay vì viết bộ trang trí bộ nhớ cache của riêng mình: 7Tham số 12 chỉ định có bao nhiêu cuộc gọi gần đây được lưu trong bộ nhớ cache. Giá trị mặc định là 128, nhưng bạn có thể chỉ định 13 để lưu trữ tất cả các cuộc gọi chức năng. Tuy nhiên, hãy lưu ý rằng điều này có thể gây ra sự cố bộ nhớ nếu bạn đang lưu trữ nhiều đối tượng lớn.>>> 8Lưu ý rằng trong cuộc gọi cuối cùng tới 08, không cần tính toán mới, vì số Fibonacci thứ tám đã được tính toán cho 09. 9Trong thư viện tiêu chuẩn, bộ đệm được sử dụng gần đây nhất (LRU) có sẵn dưới dạng 10.Trang trí này có nhiều tính năng hơn so với cái bạn thấy ở trên. Bạn nên sử dụng 10 thay vì viết bộ trang trí bộ nhớ cache của riêng mình:>>> 0Lưu ý rằng trong cuộc gọi cuối cùng tới 08, không cần tính toán mới, vì số Fibonacci thứ tám đã được tính toán cho 09. 1Trong thư viện tiêu chuẩn, bộ đệm được sử dụng gần đây nhất (LRU) có sẵn dưới dạng 10.>>> 2Lưu ý rằng trong cuộc gọi cuối cùng tới def parent(): print("Printing from the parent() function") def first_child(): print("Printing from the first_child() function") def second_child(): print("Printing from the second_child() function") second_child() first_child() 08, không cần tính toán mới, vì số Fibonacci thứ tám đã được tính toán cho def parent(): print("Printing from the parent() function") def first_child(): print("Printing from the first_child() function") def second_child(): print("Printing from the second_child() function") second_child() first_child() 09.Trong thư viện tiêu chuẩn, bộ đệm được sử dụng gần đây nhất (LRU) có sẵn dưới dạng 10. 3Trang trí này có nhiều tính năng hơn so với cái bạn thấy ở trên. Bạn nên sử dụng 10 thay vì viết bộ trang trí bộ nhớ cache của riêng mình: 4Tham số 12 chỉ định có bao nhiêu cuộc gọi gần đây được lưu trong bộ nhớ cache. Giá trị mặc định là 128, nhưng bạn có thể chỉ định 13 để lưu trữ tất cả các cuộc gọi chức năng. Tuy nhiên, hãy lưu ý rằng điều này có thể gây ra sự cố bộ nhớ nếu bạn đang lưu trữ nhiều đối tượng lớn.
Ví dụ sau đây có phần giống với ví dụ plugin đăng ký từ trước đó, ở chỗ nó không thực sự thay đổi hành vi của hàm được trang trí. Thay vào đó, nó chỉ đơn giản là thêm 16 làm thuộc tính hàm: 5Ví dụ sau đây 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:Thuộc tính chức năng 17 này sau này có thể được truy cập khi cần:
Bạn cũng có thể sửa đổi người trang trí để trả về trực tiếp 18 22. Một 22 như vậy được tạo bằng cách nhân giá trị với thiết bị. Trong 18, các đơn vị phải được tra cứu trong 25. Cơ quan đăng ký được lưu trữ như một thuộc tính hàm để tránh làm lộn xộn không gian tên:
Danh sách các khóa phải có trong JSON được đưa ra như là đối số cho người trang trí. Hàm trình bao bọc xác nhận rằng mỗi khóa dự kiến có trong dữ liệu JSON. Trình xử lý tuyến đường sau đó có thể tập trung vào công việc thực sự của mình, các lớp công nghiệp, vì nó có thể giả định một cách an toàn rằng dữ liệu JSON là hợp lệ:Nếu bạn vẫn đang tìm kiếm thêm, cuốn sách Python của chúng tôi có một phần về trang trí, cũng như cuốn sách nấu ăn Python của David Beazley và Brian K. Jones. Để biết sâu sắc về cuộc thảo luận lịch sử về cách các nhà trang trí nên được thực hiện trong Python, xem PEP 318 cũng như Wiki trang trí Python. Nhiều ví dụ về trang trí có thể được tìm thấy trong thư viện trang trí Python. Mô -đun 33 có thể đơn giản hóa việc tạo các nhà trang trí của riêng bạn và tài liệu của nó chứa các ví dụ trang trí thêm.Ngoài ra, chúng tôi đã tập hợp một tờ Cheat Cheat Decorators ngắn và ngọt ngào cho bạn: Xem bây giờ hướng dẫn này có một khóa học video liên quan được tạo bởi nhóm Python thực sự. Xem nó cùng với hướng dẫn bằng văn bản để làm sâu sắc thêm sự hiểu biết của bạn: Người trang trí Python 101 This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Python Decorators 101 Chúng ta có thể sử dụng người trang trí trên lớp trong Python không?Trang trí là một 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 chức năng hoặc lớp. Các nhà trang trí cho phép chúng ta bọc một chức năng khác để mở rộng hành vi của chức năng được bọc, mà không cần sửa đổi vĩnh viễn nó.. Decorators allow us to wrap another function in order to extend the behaviour of the wrapped function, without permanently modifying it.
Làm thế nào để bạn sử dụng các nhà trang trí trong lớp?Để trang trí một phương thức trong một lớp, trước tiên hãy sử dụng biểu tượng '@' theo sau là tên của hàm trang trí.Một người trang trí chỉ đơn giản là một hàm có chức năng như một đối số và trả về một hàm khác.Ở đây, khi chúng ta trang trí, nhân lên với integer_check, hàm số nguyên được gọi.first use the '@' symbol followed by the name of the decorator function. A decorator is simply a function that takes a function as an argument and returns yet another function. Here, when we decorate, multiply_together with integer_check, the integer function gets called.
Tại sao chúng ta sử dụng các nhà trang trí trong Python?Bạn sẽ sử dụng một bộ trang trí khi bạn cần thay đổi hành vi của một hàm mà không cần sửa đổi chức năng.Một vài ví dụ tốt là khi bạn muốn thêm ghi nhật ký, hiệu suất kiểm tra, thực hiện bộ nhớ đệm, xác minh quyền, v.v.Bạn cũng có thể sử dụng một khi bạn cần chạy cùng một mã trên nhiều chức năng.when you need to change the behavior of a function without modifying the function itself. A few good examples are when you want to add logging, test performance, perform caching, verify permissions, and so on. You can also use one when you need to run the same code on multiple functions.
Làm thế nào để các nhà trang trí làm việc trong Python?Một người trang trí trong Python là một chức năng lấy một chức năng khác làm đối số của nó và trả về một chức năng khác.Các nhà trang trí có thể cực kỳ hữu ích vì chúng cho phép mở rộng chức năng hiện có, mà không có bất kỳ sửa đổi nào đối với mã nguồn chức năng ban đầu. |