Làm cách nào để chuyển trường lớp tới trình trang trí trên phương thức lớp làm đối số?
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization["some_attr", self.url]
def get[self]:
do_work[]
Nó phàn nàn rằng self không tồn tại khi chuyển
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
46 cho người trang trí. Có cách nào để giái quyết vấn đề này không?Giải pháp tốt nhất
Đúng. Thay vì chuyển thuộc tính thể hiện vào thời điểm định nghĩa lớp, hãy kiểm tra nó khi chạy
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
Trình trang trí chặn các đối số của phương thức; . Bạn có thể chuyển tên thuộc tính dưới dạng chuỗi cho trình trang trí và sử dụng
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
47 nếu bạn không muốn mã hóa tên thuộc tínhdef check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
Giải pháp liên quan
Python – Tại sao bạn cần có đối số “self” một cách rõ ràng trong phương thức Python
Tôi thích trích dẫn Zen of Python của Peters. "Rõ ràng là tốt hơn ngầm. "
Trong Java và C++, '
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
48' có thể được suy ra, trừ khi bạn có các tên biến không thể suy ra được. Vì vậy, đôi khi bạn cần nó và đôi khi khôngPython chọn làm những thứ như thế này rõ ràng hơn là dựa trên quy tắc
Ngoài ra, vì không có gì được ngụ ý hoặc giả định, nên các phần của quá trình triển khai sẽ bị lộ.
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
49, def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
0 và các cấu trúc "nội bộ" khác có sẵn một cách rõ ràngPython – Các biến lớp tĩnh có thể có trong Python
Các biến được khai báo bên trong định nghĩa lớp, nhưng không bên trong một phương thức là các biến lớp hoặc biến tĩnh
>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
Như @ đã chỉ ra, điều này tạo ra một biến
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
1 cấp lớp, nhưng biến này khác với bất kỳ biến def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
1 cấp thể hiện nào, vì vậy bạn có thể có>>> m = MyClass[]
>>> m.i = 4
>>> MyClass.i, m.i
>>> [3, 4]
Điều này khác với C++ và Java, nhưng không quá khác với C#, nơi không thể truy cập thành viên tĩnh bằng cách sử dụng tham chiếu đến một thể hiện
Nhìn thấy
@Steve Johnson đã trả lời về các phương pháp tĩnh, cũng được ghi lại dưới
________số 8@beidy khuyến nghị s trên staticmethod, vì phương thức này sau đó nhận loại lớp làm đối số đầu tiên, nhưng tôi vẫn hơi mờ về những ưu điểm của phương pháp này so với staticmethod. Nếu bạn cũng vậy, thì có lẽ không thành vấn đề
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í
7def 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]
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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
0Nó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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
3Ở đây,
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
300 và def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
301 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
302 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
300 hoặc hàm def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
301>>>
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
9Lưu ý rằng
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
305 đề cập đến hai chức năng, nhưng theo những cách khác nhau. def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
302 và def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
307. Hàm def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
307 đượ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 hiện. Ngược lại, hàm def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
302 được viết trong dấu ngoặc đơn nên sẽ được gọi như bình thườngchứ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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
5Điều gì xảy ra khi bạn gọi hàm
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
310? . Đầu ra sẽ như sau>>>
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
7Lư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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
310. chúng chỉ tồn tại bên trong hàm def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
310 dưới dạng biến cục bộ. Hãy thử gọi def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
313. Bạn sẽ nhận được một lỗidef check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
1Bất cứ khi nào bạn gọi
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
310, các hàm bên trong def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
313 và def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
316 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
310Hà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 bên ngoài
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
310def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
7Lưu ý rằng bạn đang trả về
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
319 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
319. Ngược lại def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
313 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>>>
>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
1Đầu ra hơi khó hiểu chỉ đơn giản có nghĩa là biến
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
322 đề cập đến hàm def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
313 cục bộ bên trong def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
310, trong khi def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
325 trỏ đến def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
316Giờ đây, bạn có thể sử dụng
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
322 và def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
325 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>>>
>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
9Cuố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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
313. 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
319—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áotrang 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
331 không? >>>
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
30Để 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
31Trên thực tế, tên
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
332 hiện trỏ đến hàm bên trong def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
333. Hãy nhớ rằng bạn trả về def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
334 như một hàm khi bạn gọi def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
335>>>
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
32Tuy nhiên,
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
333 có tham chiếu đến def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
331 ban đầu là def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
338 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
333 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àydef check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
33Nếu bạn cố gọi cho
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
331 sau giờ đi ngủ, sẽ không có chuyện gì xảy ra>>>
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
34Cú pháp đặc biệt
Cách bạn trang trí
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
331 ở trên hơi rườm rà. Trước hết, bạn phải gõ tên def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
332 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ăngThay 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
344, đôi khi được gọi là. Ví dụ sau đây thực hiện chính xác điều tương tự như ví dụ trang trí đầu tiêndef check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
35Vì vậy,
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
345 chỉ là một cách dễ dàng hơn để nói def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
346. Đó là cách bạn áp dụng một trình trang trí cho một chức năngLoại bỏ các quảng cáoTá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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
347 với nội dung saudef check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
36Ghi 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
333 thường được chấp nhận. 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
349Bâ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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
37Khi bạn chạy ví dụ này, bạn sẽ thấy rằng bản gốc
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
331 được thực thi hai lần>>>
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
38Tiề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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
39Thật không may, chạy mã này gây ra lỗi
>>>
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
90Vấn đề là hàm bên trong
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
351 không nhận bất kỳ đối số nào, nhưng def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
352 đã đượ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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
351 chấp nhận một đối số, nhưng sau đó nó sẽ không hoạt động đối với hàm def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
331 mà bạn đã tạo trước đóGiải pháp là sử dụng
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
355 và def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
356 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
347 như saudef check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
91Hàm bên trong
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
351 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
331 và def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
360 của bạn đều hoạt động>>>
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
92Loại bỏ các quảng cáoTrả 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
93Cố gắng sử dụng nó
>>>
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
94Rất tiếc, trình trang trí của bạn đã ăn giá trị trả về từ hàm
Bởi vì
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
361 không trả về giá trị một cách rõ ràng, cuộc gọi def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
362 đã 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
347 của bạndef check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
95Giá trị trả về từ lần thực thi cuối cùng của hàm được trả về
>>>
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
96Bạ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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
97Việ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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
98Tuy nhiên, sau khi được trang trí,
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
331 đã 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
351 bên trong trình trang trí def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
367. 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, người trang trí nên sử dụng bộ trang trí, bộ trang trí này sẽ lưu giữ thông tin về chức năng ban đầu. Cập nhật lại
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
347def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
99Bạn không cần thay đổi bất cứ điều gì về chức năng
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
331 được trang trí>>>
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
50Tốt hơn nhiều. Bây giờ
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
331 vẫn là chính nó sau khi trang tríChi tiết kỹ thuật. Trình trang trí
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
368 hàm def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
373 để cập nhật các thuộc tính đặc biệt như def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
374 và def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
375 được sử dụng trong phần nội quanLoại bỏ các quảng cáoMộ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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
51Cô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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
347 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àychức năng thời gian
Hãy bắt đầu bằng cách tạo một trình trang trí
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
377. 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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
52Trì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 ____1378] và ngay sau khi chức năng kết thúc [tại ____1379]. Thời gian mà chức năng cần sau đó là sự khác biệt giữa hai [tại
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
380]. Chúng tôi sử dụng chức năng 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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
53Chạ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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
377 rất tuyệt nếu bạn chỉ muốn biết 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
383 trong thư viện chuẩn. Nó tạm thời vô hiệu hóa và chạy nhiều thử nghiệm để loại bỏ tiếng ồn khỏi các cuộc gọi chức năng nhanhMã gỡ lỗi
Trình trang trí
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
384 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ọidef check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
54Chữ 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ã
- Tạo một danh sách các đối số vị trí. Sử dụng
385 để có được một chuỗi đẹp đại diện cho mỗi đối sốdef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
- 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à
386 trong đó chỉ địnhdef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
387 có nghĩa làdef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
385 được sử dụng để biểu thị giá trịdef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
- 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
- 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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
55Lưu ý cách trình trang trí
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
384 in chữ ký và giá trị trả về của hàm def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
390>>>
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
56Ví dụ này có vẻ không hữu ích ngay lập tức vì trình trang trí
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
384 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ếpVí 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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
57Ví 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
392, bạn có thể thấy trình trang trí def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
384 đang hoạt động>>>
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
58Trong 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áoLà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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
394 sẽ ngủ một giây trước khi nó gọi chức năng trang trídef check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
59Để xem tác dụng của trình trang trí
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
394, bạn thực sự cần phải tự mình chạy ví dụ>>>
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
70Ghi chú. Hàm
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
396 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 PythonTrình trang trí
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
394 luôn ngủ trong một giâ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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
71Trình trang trí
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
398 chỉ đơn giản là lưu trữ một tham chiếu đến chức năng được trang trí trong lệnh chính tả def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
399 toàn cầu. Lưu ý rằng bạn không cần phải viết một hàm bên trong hoặc sử dụng def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
368 trong ví dụ này vì bạn đang trả về hàm ban đầu chưa sửa đổiHàm
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
901 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
399 đã chứa các tham chiếu đến từng đối tượng chức năng được đăng ký làm plugin>>>
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
72Lợ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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
398Nếu bạn đã quen thuộc với
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
904 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
904 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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
73Sử dụng trình trang trí
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
398, 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
904 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
908 chỉ hiển thị với người dùng đã đăng nhập hoặc được xác thựcdef check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
74Mặ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 thay thế, điều này bổ sung thêm tính bảo mật và chức năng
Loại bỏ các quảng cáotrang 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
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. Điều này là để 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
909, def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
910 và def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
911. Các trình trang trí def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
909 và def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
910 đượ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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
911 đượ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àyVí 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 lớp
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
915 sử dụng các bộ trang trí def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
909, def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
910 và def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
911def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
75Trong lớp học này
919 là một phương pháp thông thườngdef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
920 là một tài sản 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 đơndef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
921 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ứcdef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
922. 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 đơndef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
923 là một phương thức lớp. Nó không bị ràng buộc với một phiên bản cụ thể củadef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
915. 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ớpdef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
925 là một phương thức tĩnh. Nó không thực sự phụ thuộc vào lớpdef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
915, 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ớpdef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
Ví dụ, lớp
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
915 có thể được sử dụng như sau>>>
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
76Hã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 và trang trí từ
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
77Sử dụng lớp này, bạn có thể thấy tác dụng của các trang trí
>>>
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
78Mộ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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
930 mới trong Python 3. 7def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
79Ý 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
931A 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ả những người trang trí sẽ hoạt động như những người 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
377 được áp dụng cho một lớpdef check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
10Trang 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
377 chỉ là viết tắt của def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
934Ở đây,
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
377 chỉ đo thời gian cần thiết để khởi tạo lớp>>>
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
11, 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
936, đảm bảo rằng chỉ có một thể hiện của một lớpLoạ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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
12Hã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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
384 gọi def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
938, gọi def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
360 hoặc def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
940>>>
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
13Quan sát sự khác biệt nếu chúng ta thay đổi thứ tự của
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
384 và def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
938def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
14Trong trường hợp này,
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
938 cũng sẽ được áp dụng cho def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
384>>>
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
15Trang 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
938 có thể được mở rộng thành một trang trí def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
946. 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
16>>>
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
17Hã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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
344 đã đề 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
948 để 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. Nói chung, bạn muốn một cái gì đó như saudef check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
18Thô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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
19Có 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 vào bên trong một
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
949 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ùngdef check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
70Hàm
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
950 này nhận các đối số tùy ý và trả về giá trị của hàm được trang trí, def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
951. Hàm bao bọc này cũng chứa vòng lặp gọi hàm được trang trí def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
952 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
952 phải được cung cấp từ bên ngoàiMột bước ra ngoài, bạn sẽ tìm thấy chức năng trang trí
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
71Một lần nữa,
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
954 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 tôi đặt tên cơ sở—def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
955—cho chức năng ngoài cùng, là chức năng mà người dùng sẽ gọiNhư bạn đã thấy, hàm ngoài cùng trả về một tham chiếu đến hàm trang trí
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
72Có một vài điều tế nhị xảy ra trong hàm
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
955- Xác định
954 là một hàm bên trong có nghĩa làdef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
955 sẽ tham chiếu đến một đối tượng hàm—def check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
959. Trước đó, chúng tôi đã sử dụngdef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
960 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ốdef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
- Đối số
952 dường như không được sử dụng trong chínhdef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
955. Nhưng bằng cách chuyểndef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
952, một bao đóng được tạo trong đó giá trị củadef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
952 được lưu trữ cho đến khi nó được sử dụng sau này bởidef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
950def check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
Với mọi thứ đã được thiết lập, hãy xem kết quả có như mong đợi không
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
16>>>
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
17Chỉ là kết quả mà chúng tôi đang hướng tới
Loại bỏ các quảng cáoLà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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
966 đặc biệt, có nghĩa là tất cả các tham số sau đây chỉ dành cho từ khóadef check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
75Ở đây, đối số
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
967 đó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- Nếu
968 đã đượ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ạngdef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
967. Nếu nó đã được gọi với các đối số, thìdef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
967 sẽ làdef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
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 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]
966 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ídef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
- 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
- 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
973 trong phần trước, bạn có thể viết như saudef check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
76So sánh điều này với bản gốc
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
973. Những thay đổi duy nhất là tham số def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
967 được thêm vào và def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
976-def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
977 ở cuốiCô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
Những ví dụ này cho thấy rằng
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
973 hiện có thể được sử dụng có hoặc không có đối sốdef check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
77Nhớ lại rằng giá trị mặc định của
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
952 là 2>>>
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
78trang 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ú. Trong , 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 này, 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
79Trạng thái—số lần gọi hàm—được lưu trữ trong thuộc tính hàm
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
981 trên hàm bao bọc. Đây là tác dụng của việc sử dụng nó>>>
>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
10Loại bỏ các quảng cáoCá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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
982 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
345 chỉ là một cách dễ dàng hơn để nói def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
984. Do đó, nếu def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
985 là một lớp, thì nó cần lấy def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
338 làm đối số trong phương thức def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
987 của nó. Hơn nữa, thể hiện của lớp cần phải sao cho 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
988>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
11Phương thức
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
988 được thực thi mỗi khi bạn cố gắng gọi một thể hiện của lớp>>>
>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
12Do đó, một triển khai điển hình của lớp trang trí cần triển khai
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
987 và def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
988>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
13Phương thức
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
987 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
988 sẽ được gọi thay vì hàm được trang trí. Về cơ bản, nó thực hiện giống như hàm def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
333 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 chức năng thay vì def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
368Công cụ trang trí
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
997 này hoạt động giống như công cụ trang trí trong phần trước>>>
>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
10Nhiề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 đó, chúng tôi 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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
394 bằng cách sử dụng đối số def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
500 tùy chọn để kiểm soát thời gian ngủ của nó>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
15Chúng tôi đang sử dụng bản soạn sẵn được giới thiệu trong phần này để làm cho
def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
394 có thể gọi được cả khi có và không có đối số. Hàm đệ quy tương tự def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
396 hiện ngủ hai giây giữa mỗi lần đếm>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
16Như trước đây, bạn phải tự chạy ví dụ để xem tác dụng của trình trang trí
>>>
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
70Tạ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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
504 và def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
505. 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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
508, như bạn đã thấy trong phần>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
18Sử dụng
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
508 chỉ trả về def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
504 cho các đối tượng giống hệt nhau. Trình trang trí def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
936 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ữ>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
19Như 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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
512 thay vì def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
338 làm tên tham số để chỉ ra rằng nó có nghĩa là trang trí lớpHãy xem nếu nó hoạt động
>>>
>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
90Có vẻ như rõ ràng rằng
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
514 thực sự là cùng một ví dụ với def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
515Ghi 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
>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
91Mặ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ệ
>>>
>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
92Để 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. Cần tính toán 21891 cho
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
516 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ếtGiải pháp thông thường là triển khai các số Fibonacci bằng vòng lặp
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
517 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>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
93Bộ đệm hoạt động như một bảng tra cứu, do đó, bây giờ
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
518 chỉ thực hiện các phép tính cần thiết một lần>>>
>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
94Lưu ý rằng trong cuộc gọi cuối cùng tới
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
519, không cần tính toán mới, vì số Fibonacci thứ tám đã được tính toán cho def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
520Trong thư viện tiêu chuẩn, bộ nhớ đệm Ít được sử dụng Gần đây nhất [LRU] có sẵn dưới dạng
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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
521 thay vì viết trình trang trí bộ đệm của riêng bạn>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
95Tham số
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
523 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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
524 để 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ớnBạn có thể sử dụng phương pháp
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
525 để 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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
523 nhỏ giả tạo để xem tác động của việc xóa các phần tử khỏi bộ đệm>>>
>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
96Thêm thông tin về đơn vị
Ví dụ sau hơi giống với ví dụ 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ỉ cần thêm
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
527 làm thuộc tính chức năng>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
97Ví 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
>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
98Thuộc tính hàm
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
528 này sau này có thể được truy cập khi cần>>>
>>> class MyClass:
.. i = 3
...
>>> MyClass.i
3
99Lư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]
0Tuy nhiên, vì các chú thích được sử dụng cho các gợi ý loại, sẽ khó kết hợp các đơn vị như chú thích với
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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
529. Ví dụ, với def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
529 đã cài đặt [def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
531], 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]
1Bạn cũng có thể sửa đổi trình trang trí để trả lại trực tiếp một
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
529 def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
533. Một def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
533 như vậy được tạo bằng cách nhân một giá trị với đơn vị. Trong def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
529, các đơn vị phải được tra cứu trong một def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
536. 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êndef 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]
2Với trình trang trí
def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
537, 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]
3Xá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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
538 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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
539 sau đây sẽ thực hiện công việcdef 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]
5Trong đ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
- Danh sách các khóa phải có trong JSON được đưa ra làm đối số cho trình trang trí
- 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]
6Phầ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 xem xét 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
368 để trông giống chức năng được trang trí hơndef check_authorization[f]: def wrapper[*args]: print args[0].url return f[*args] return wrapper class Client[object]: def __init__[self, url]: self.url = url @check_authorization def get[self]: print 'get' >>> Client['//www.google.com'].get[] //www.google.com get
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 check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
355 và def check_authorization[f]:
def wrapper[*args]:
print args[0].url
return f[*args]
return wrapper
class Client[object]:
def __init__[self, url]:
self.url = url
@check_authorization
def get[self]:
print 'get'
>>> Client['//www.google.com'].get[]
//www.google.com
get
356 để 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 bằng ba câu lệnh def check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
543Bạ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 check_authorization[attribute]:
def _check_authorization[f]:
def wrapper[self, *args]:
print getattr[self, attribute]
return f[self, *args]
return wrapper
return _check_authorization
544 có thể đơn giản hóa việc tạo trình trang trí của riêng bạn và mô-đun này chứa các ví dụ về trình trang trí khácNgoà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 ArneMỗ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ẻ EmailBà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. 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