Trong Python, trình trang trí cho phép người dùng thêm các chức năng hữu ích vào đối tượng hiện có. Để sử dụng một công cụ trang trí, chúng tôi sử dụng ký hiệu
@mydecorator2
@mydecorator1
def myfunction[]:
pass
5 theo sau là tên của một công cụ trang trí@mydecorator
def myfunction[]:
pass
Khi gọi
@mydecorator2
@mydecorator1
def myfunction[]:
pass
6, decorator @mydecorator2
@mydecorator1
def myfunction[]:
pass
7 được gọi đầu tiên trước khi thực hiện @mydecorator2
@mydecorator1
def myfunction[]:
pass
8Trang trí có thể được xếp chồng lên nhau. Trong ví dụ bên dưới, khi chúng ta cố gắng gọi
@mydecorator2
@mydecorator1
def myfunction[]:
pass
6, @mydecorator[5]
def myfunction[]:
pass
0 được gọi đầu tiên, tiếp theo là @mydecorator[5]
def myfunction[]:
pass
1 và sau đó @mydecorator2
@mydecorator1
def myfunction[]:
pass
8 được gọi cuối cùng@mydecorator2
@mydecorator1
def myfunction[]:
pass
Trình trang trí cũng có thể chấp nhận các đối số tương tự như hàm
@mydecorator[5]
def myfunction[]:
pass
Trang trí cũng có thể được sử dụng với các lớp
@mydecorator
def myfunction[]:
pass
1Viết trang trí tùy chỉnh
Nhưng làm thế nào để chúng ta viết các trang trí tùy chỉnh của riêng mình? . Có nhiều cách "sáng tạo" khác để viết một trình trang trí nhưng chúng ta sẽ chỉ bám vào các hàm. Dưới đây là 3 ví dụ hữu ích
Trang trí không có đối số
Giả sử chúng ta muốn tạo một trình trang trí để lưu vào bộ nhớ đệm các kết quả từ các hàm. Đầu tiên, chúng ta sẽ sử dụng mẫu sau
@mydecorator
def myfunction[]:
pass
2Trong ví dụ trên,
@mydecorator[5]
def myfunction[]:
pass
3 được lồng trong @mydecorator2
@mydecorator1
def myfunction[]:
pass
7. Đây là cách trang trí được viết. @mydecorator2
@mydecorator1
def myfunction[]:
pass
7 chấp nhận đối tượng hàm @mydecorator[5]
def myfunction[]:
pass
6 làm đối số trỏ đến hàm mà chúng ta đang áp dụng trình trang trí cho. Mục đích của @mydecorator[5]
def myfunction[]:
pass
3 là chấp nhận các đối số dành cho hàm @mydecorator[5]
def myfunction[]:
pass
6. Trên dòng 3 là lời gọi hàm thực tế, @mydecorator[5]
def myfunction[]:
pass
9. Hãy lưu ý rằng @mydecorator2
@mydecorator1
def myfunction[]:
pass
7 chỉ trả về đối tượng @mydecorator2
@mydecorator1
def myfunction[]:
pass
0 và không gọi nóMột ứng dụng ví dụ là để tạo trình trang trí "bộ đệm". Trình trang trí bộ nhớ đệm rất hữu ích cho các chức năng chậm khi chúng tôi lưu trữ kết quả của hàm cho đối số cụ thể mà nó đã chấp nhận. Điều này hữu ích nếu kết quả của hàm sẽ không bao giờ thay đổi hoặc không bị ảnh hưởng bởi các yếu tố khác ngoài chính các đối số. Dưới đây là một thực hiện ngây thơ
@mydecorator2
@mydecorator1
def myfunction[]:
pass
2Trong ví dụ này, chúng tôi sử dụng ID hàm, các đối số vị trí của nó
@mydecorator
def myfunction[]:
pass
12 và các đối số từ khóa của nó @mydecorator
def myfunction[]:
pass
13 làm khóa cho dữ liệu được lưu trong bộ nhớ cache của chúng tôi. Chúng tôi đã chuyển đổi nó thành một chuỗi JSON vì từ điển Python có thể không băm được một số đối tượng [e. g. một @mydecorator
def myfunction[]:
pass
14 không thể băm được]. Chúng tôi đã sắp xếp các đối số từ khóa theo cách đệ quy để đảm bảo các từ điển chưa được sắp xếp sẽ dẫn đến cùng một giá trịĐể sử dụng trình trang trí
@mydecorator
def myfunction[]:
pass
15, chỉ cần thêm @mydecorator
def myfunction[]:
pass
16 vào phần khai báo hàm@mydecorator2
@mydecorator1
def myfunction[]:
pass
8Chúng tôi đã thêm ghi nhật ký để kiểm tra những gì đang xảy ra trong nội bộ. Lưu ý rằng trong lần gọi hàm thứ 3, nó không sử dụng dữ liệu đã lưu trong bộ nhớ cache. Điều đã xảy ra ở đây là
@mydecorator
def myfunction[]:
pass
17 đã được đưa vào @mydecorator
def myfunction[]:
pass
13 chứ không phải trong @mydecorator
def myfunction[]:
pass
12@mydecorator2
@mydecorator1
def myfunction[]:
pass
2Trang trí với đối số
Trình trang trí có thể chấp nhận các đối số giống như các chức năng bình thường. Khi viết loại trình trang trí này, chúng tôi chỉ cần thêm một chức năng lồng nhau khác vào mẫu ban đầu của chúng tôi
@mydecorator2
@mydecorator1
def myfunction[]:
pass
3Sự khác biệt bây giờ là hàm ngoài cùng
@mydecorator2
@mydecorator1
def myfunction[]:
pass
7 giờ đây sẽ chấp nhận các đối số tùy chỉnh cho hàm trang trí, @mydecorator[5]
def myfunction[]:
pass
3 sẽ chấp nhận đối tượng hàm và @mydecorator
def myfunction[]:
pass
22 chấp nhận các đối số dành cho hàm được trang tríCải thiện trình trang trí bộ nhớ đệm của chúng tôi trước đó, chúng tôi muốn giới hạn số lượng dữ liệu được lưu trong bộ nhớ cache tối đa làm ví dụ. Những gì chúng tôi sẽ triển khai là các khóa cũ sẽ bị xóa khi dữ liệu mới được thêm vào và nó vượt quá giới hạn
@mydecorator2
@mydecorator1
def myfunction[]:
pass
7Hãy để chúng tôi kiểm tra trình trang trí của chúng tôi với giới hạn 3 mục chỉ bằng cách sử dụng mã bên dưới
@mydecorator2
@mydecorator1
def myfunction[]:
pass
0Sau khi thực thi đoạn mã trên, chúng tôi sẽ nhận thấy rằng mục đầu tiên đã bị xóa trong lệnh gọi
@mydecorator
def myfunction[]:
pass
23 thứ 4@mydecorator2
@mydecorator1
def myfunction[]:
pass
1Trang trí lớp học
Viết decorator cho class cũng giống như viết decorator cho hàm. Trong ví dụ này, chúng tôi sẽ mô phỏng chức năng
@mydecorator
def myfunction[]:
pass
24 được tìm thấy trong các ngôn ngữ lập trình khác. @mydecorator
def myfunction[]:
pass
24 chỉ đơn giản là một mẫu kế thừa@mydecorator2
@mydecorator1
def myfunction[]:
pass
2Trong ví dụ trên, chúng ta chỉ đơn giản tạo một class mới từ 2 tham số là
@mydecorator
def myfunction[]:
pass
26 và @mydecorator
def myfunction[]:
pass
27. Bởi vì chúng tôi không cần bất kỳ đối số bổ sung nào cho một lớp, chúng tôi chỉ có một hàm lồng nhau hai cấpVí dụ, hãy mở rộng lớp
@mydecorator
def myfunction[]:
pass
28 với @mydecorator
def myfunction[]:
pass
29@mydecorator2
@mydecorator1
def myfunction[]:
pass
3Ví dụ trên sẽ xuất ra
@mydecorator2
@mydecorator1
def myfunction[]:
pass
4Sự kết luận
Viết trang trí tùy chỉnh là đơn giản và thú vị để làm. Chúng tôi cũng đã học được rằng chúng tôi có thể lồng các chức năng và kế thừa động là có thể