Trình trang trí trong lớp Python là gì?

Decorators là một công cụ quan trọng và hữu ích của Python. Nó cho phép chúng ta sửa đổi hành vi của hàm hoặc lớp. Cho đến giờ, chúng ta đã học cách tạo các bộ trang trí bằng cách sử dụng hàm, nhưng ở đây chúng ta sẽ thảo luận về việc định nghĩa một lớp làm bộ trang trí. Trong hướng dẫn này, chúng ta sẽ học cách trang trí lớp. Bạn đã quen thuộc với những người trang trí;

Trình trang trí cho phép chúng tôi bọc một chức năng khác để mở rộng hành vi của chức năng được bọc mà không thay đổi vĩnh viễn nó

Hãy xem ví dụ sau

Ví dụ -

đầu ra

**********
50
**********

Giải trình -

Trong đoạn mã trên, chúng ta đã tạo trình trang trí star[], lấy một số nguyên làm đối số và trả về một giá trị có thể gọi được. Hàm có thể gọi được lấy hàm func làm đối số, một hàm sẽ được trang trí. Ngoài ra, có thể gọi được có thể truy cập n từ nhà máy trang trí

Bây giờ chúng tôi sẽ triển khai trình trang trí này bằng cách sử dụng lớp Python

Trình trang trí lớp Python

Để xác định trình trang trí lớp, chúng ta cần sử dụng phương thức __call__[] của các lớp. Khi chúng ta cần tạo một đối tượng hoạt động giống như một hàm, trình trang trí chức năng phải trả về một đối tượng hoạt động giống như một hàm. Hãy hiểu ví dụ sau

Ví dụ 1

đầu ra

Giải trình -

Chúng tôi đã tạo trình trang trí đơn giản bằng cách sử dụng trình trang trí lớp bằng phương thức __call__. Chúng ta có thể sửa đổi nó như chúng ta muốn. Bây giờ, chúng ta viết lại đoạn mã trên bằng cách sử dụng trình trang trí lớp

Ví dụ - 2

đầu ra

Giải trình -

Mẫu [5] trả về một phiên bản của Mẫu và phiên bản đó có thể gọi được nên nó sẽ hoạt động như bên dưới

Trình trang trí lớp với Tuyên bố trả về

Chúng ta có thể sử dụng câu lệnh return trong trình trang trí lớp. Trong ví dụ trước, chúng tôi đã không trả lại bất cứ thứ gì, vì vậy không có vấn đề gì. Nhưng đôi khi, chúng ta cần trả về giá trị. Chúng tôi có thể làm điều đó như dưới đây

Ví dụ -

đầu ra

Given number is: 25
Cube of number is: 15625

Giải trình -

Trong đoạn mã trên, chúng ta đã tạo lớp CubeDecorataor làm công cụ trang trí và gọi phương thức __call__[]. Trong __call__[] chúng ta đã gọi hàm gọi và trả về kết quả

Sử dụng Trình trang trí lớp để in thời gian thực hiện chương trình

Chúng tôi sử dụng mô-đun thời gian với phương thức __call__ để lấy thời gian thực hiện chương trình. Hãy hiểu ví dụ sau

Ví dụ -

đầu ra

Execution took 4.004076242446899 seconds

Giải trình -

Chúng tôi đã nhập phương thức thời gian là t từ mô-đun thời gian trong đoạn mã trên. Sau đó, chúng tôi đã tạo lớp ExecutTimer làm công cụ trang trí, nơi chúng tôi có thời gian bắt đầu khi chương trình bắt đầu thực thi và thời gian kết thúc khi chương trình kết thúc. Chúng tôi đã trừ thời gian bắt đầu từ thời gian kết thúc và nhận được thời gian thực hiện chương trình

Phần kết luận

Trong hướng dẫn này, chúng tôi đã đề cập đến trình trang trí lớp với một số ví dụ. Trình trang trí là một công cụ quan trọng trong Python, nó thay đổi hành vi của chức năng khác mà không thay đổi cách triển khai thực tế của nó. Hầu hết thời gian, chúng tôi sử dụng các hàm Python để xác định các bộ trang trí, nhưng các bộ trang trí lớp cũng hữu ích và nâng cao khả năng đọc mã. Các trình trang trí lớp có thể được mở rộng dưới dạng lấy các đối số hoặc quay trở lại mặc định nếu không có đối số nào được thông qua

Bạn đã bao giờ tự hỏi làm thế nào một toán tử trang trí python [“@”] hoạt động chưa?

Hôm nay mình sẽ hướng dẫn các bạn cách hiện thực và sử dụng decorator trong python 3

THẬN TRỌNG. Đừng nhầm lẫn giữa decorator — biểu thị toán tử trang trí “@” — với Decorator Design Pattern

Trang trí là gì?

Python là ngôn ngữ lập trình hạng nhất, có nghĩa là các hàm có thể được truyền xung quanh dưới dạng đối số, giống như bất kỳ đối tượng nào khác. Điều này cho phép tồn tại các hàm bậc cao hơn [HOF] có thể nhận và/hoặc trả về các hàm khác

Một trang trí về cơ bản là một HOF;

Hãy xem ví dụ sau

Ở đây, validate_is_function_signature_funky được sử dụng làm công cụ trang trí. Nó kiểm tra chữ ký của hàm mà nó trang trí, cụ thể là hàm funky_function và đưa ra lỗi nếu chữ ký của hàm không hợp lệ. Trong trường hợp này, trình trang trí không quan tâm đến giá trị trả về cũng như bản thân đầu vào

Trình trang trí về cơ bản là đường cú pháp. Hãy nhìn vào đây

Bằng cách trang trí một chức năng, bạn khéo léo cung cấp cho nó chức năng “đặc biệt” và xác định lại chức năng đó bằng các tính năng bổ sung

Bây giờ chúng ta đã có một ý tưởng sơ bộ về những gì một người trang trí có thể làm, hãy để chúng ta tìm hiểu sâu hơn về những người trang trí và cách họ làm việc

Chức năng trang trí

Trình trang trí chức năng là một HOF lấy chức năng [đối tượng trang trí] làm đầu vào

Trường hợp 1 - trang trí không có đầu vào trực tiếp

Đôi khi trình trang trí không cần đầu vào bổ sung nào ngoài chức năng mà nó trang trí và các đối số của nó. Đây là một triển khai lớp của trình trang trí của chúng tôi

Rất nhiều thứ đang diễn ra ở đây, vì vậy hãy đi sâu vào. Đây là những gì đang xảy ra đằng sau hiện trường tại

  • thời gian trang trí

  • thời gian gọi

Đây là lý do tại sao __call__ được gọi với các đầu vào chức năng

Bạn cũng có thể triển khai các trình trang trí không có đầu vào bằng các hàm

Bạn có thể nói, những gì đang xảy ra ở đây?

Trường hợp 2 - trang trí với đầu vào trực tiếp

Nhưng nếu bạn cần chuyển trực tiếp [các] đối số cho trình trang trí của mình thì sao? . Hãy xem việc triển khai lớp sau

à há. Một cái gì đó thú vị đã xảy ra ở đây. Bạn có thể cho biết, tại sao điều này là?

Bởi vì ban đầu chúng ta đã truyền đối số cho trình trang trí, nên chúng ta phải truyền hàm trong lần gọi tiếp theo. Đây là những gì đang xảy ra tại

  • Thời gian trang trí [cả __init__ và __call__ được gọi]

  • Thời gian gọi [hàm được trả về bởi __call__ hiện được gọi với các đối số my_function, cụ thể là a, b và c

Bạn cũng có thể triển khai một trình trang trí như vậy bằng cách sử dụng các hàm. Bạn cần tạo hai hàm lồng nhau vì bản thân hàm trang trí sẽ được gọi với đầu vào của chính nó trước, sau đó là hàm bên trong với hàm trang trí làm đối số đầu vào. Cuối cùng, khi gọi hàm được trang trí, hàm bên trong nhất sẽ được gọi, lấy đầu vào của hàm được trang trí

Bây giờ bạn sẽ có thể nói những gì đang xảy ra đằng sau hiện trường. Vì vậy, tôi sẽ để lại cái này như một bài tập cho bạn

Nếu bạn đang tự hỏi những trường hợp sử dụng thực tế nào dành cho trình trang trí trong python, hãy xem thư viện python này có nhiều ví dụ như vậy. Chúng ta hãy xem xét một trường hợp sử dụng thực tế của người trang trí

Điều đó làm cho mã dễ đọc hơn. Lưu ý rằng nó cũng giới thiệu khớp nối lỏng lẻo hơn giữa các thành phần khác nhau và tăng cường đáng kể khả năng phục hồi của các chức năng. tôi thích nó

Trang trí lớp học

Một trình trang trí lớp là một trình trang trí một đối tượng lớp python. Nó hoạt động giống như trong trường hợp của hàm, ngoại trừ đối tượng được trang trí là một lớp. Bạn có thể đoán rằng trình trang trí mà bạn đang triển khai sẽ trả về một tham chiếu đến lớp có thứ tự cao hơn, sau đó

Một ví dụ về trình trang trí lớp là một ví dụ khi được sử dụng sẽ nhân mọi phương thức của lớp. Tất nhiên, một cách để đạt được điều đó là sử dụng một hàm trang trí, hãy gọi nó là time_this, như vậy

class ImportantStuff[object]:     
@time_this

def do_stuff_1[self]:
..
@time_this

def do_stuff_2[self]:
...
@time_this
def do_stuff_3[self]:
...

Việc triển khai trình trang trí ở trên giống hệt với chức năng độc lập, vì vậy tôi sẽ để bạn thực hiện nó như một thông lệ

Nhưng chúng ta có thể làm tốt hơn bằng cách đơn giản là trang trí toàn bộ lớp bằng cách sử dụng trình trang trí lớp

@time_all_class_methods 
class ImportantStuff:
def do_stuff_1[self]:
...
def do_stuff_2[self]:
...

Điều này giúp loại bỏ sự tẻ nhạt của việc thêm trình trang trí vào mọi chức năng. Trình trang trí trong trường hợp này nên kiểm tra xem thuộc tính đang được truy cập có phải là một phương thức của lớp hay không, mỗi khi đạt đến một thể hiện của lớp đó. Nếu đúng, thì nó gọi hàm đó và ghi lại thời gian trước và sau khi phương thức được gọi

May mắn thay, điều này có thể thực hiện được thông qua các bộ trang trí, miễn là bộ trang trí trả về một lớp đặc biệt. Lớp chúng ta cần triển khai phải có triển khai “__getattribute__” tùy chỉnh để kiểm tra thủ công xem thuộc tính đang được truy cập thuộc về lớp được trang trí hay của chính nó. Nếu phương thức không thuộc lớp trang trí đơn giản, điều đó có nghĩa là nó thuộc lớp trang trí, vì vậy chúng ta sẽ phải tính thời gian cho nó. Đó là tất cả

Hãy xem cách triển khai bên dưới. Thoạt nhìn có vẻ phức tạp, nhưng đó thực sự là tất cả những gì cần làm. Đây là cách chúng ta có thể đạt được điều này

Lưu ý rằng trình trang trí trả về lớp Trình bao bọc ở mức cao nhất. Điều này có nghĩa là tại thời điểm trang trí, MyClass được định nghĩa lại như một loại lớp “bao bọc” MyClass. Sử dụng đầu ra được đề cập trong ví dụ trên, chúng ta có thể hiểu rõ hơn về điều này

  • Dòng 71–72. Thời kỳ trang trí
MyClass = Wrapper  # That's it!
  • Dòng 73 — 76. Khởi tạo MyClass
instance = MyClass[]  #  Wrapper[MyClass][]
  • Dòng 77 — 81. Phương thức hạng nhất được gọi
instance.method_x[]  #  Wrapper[MyClass][MyClass.method_x]
  • Dòng 83 — 87. Phương thức lớp thứ hai được gọi
________số 8

Đây là lý do tại sao chúng ta cần triển khai thủ công hàm __getattribute__ dunder cho hàm bao bọc của mình

Tập thể dục. làm cách nào chúng ta có thể triển khai trình trang trí lớp trực tiếp nhận đầu vào của chính nó tại thời điểm trang trí?

Trang trí cực kỳ mạnh mẽ và có thể làm cho cuộc sống dễ dàng hơn. Không dễ để làm quen với chúng trước, nhưng nếu được sử dụng đúng cách, chúng có thể giải quyết vấn đề tốt. Trình trang trí lớp rõ ràng phức tạp hơn một chút so với trình trang trí chức năng

Trước tiên, hãy hiểu vấn đề bạn đang cố gắng giải quyết. Bạn có quan tâm đến chính hàm đó, các đối số của nó, giá trị trả về hoặc sự kết hợp của chúng không?

TL;DR — Tóm tắt

Trình trang trí là cách của python để thao tác các phần tử của ngôn ngữ python. Về cơ bản, chúng là các hàm bậc cao lấy các phần tử mà chúng trang trí làm đầu vào và có thể nắm bắt đầu vào và đầu ra của đối tượng

Trường hợp sử dụng mẫu sẽ là trình trang trí bộ nhớ đệm lưu trữ cặp khóa-giá trị của đầu vào và đầu ra của hàm

@cache_io  # caches the results
def fibo[n]:
if n in [0, 1]:
return n
return fibo[n - 1] + fibo[n - 2]

Thông thường, các bộ trang trí có thể được triển khai dưới dạng các hàm trả về các hàm hoặc các lớp

Người trang trí có thể có hoặc không có đối số. Nếu họ làm như vậy, nó sẽ thay đổi luồng trang trí và sau đó là việc gọi hàm được trang trí hoặc thể hiện của lớp. Do đó, việc triển khai sẽ cần điều chỉnh thêm một chút

Đây là một bộ sơ đồ đẹp cho các bộ trang trí chức năng

Trình trang trí chức năng không có đối số đầu vào

Trình trang trí chức năng với các đối số đầu vào

Nếu được sử dụng đúng cách, các trình trang trí có thể làm cho mã của bạn dễ đọc hơn và loại bỏ các thao tác trừu tượng không cần phải kết hợp quá chặt chẽ với mã của bạn

Tại sao trình trang trí được sử dụng trong Python?

Bạn sẽ sử dụng trình trang trí khi bạn cần thay đổi hành vi của một hàm mà không cần sửa đổi chính hàm đó . Một vài ví dụ điển hình là khi bạn muốn thêm ghi nhật ký, kiểm tra hiệu suất, thực hiện lưu vào bộ nhớ đệm, xác minh quyền, v.v. Bạn cũng có thể sử dụng một mã khi cần chạy cùng một mã trên nhiều chức năng.

Là một trang trí một lớp học?

Công cụ trang trí lớp là công cụ trang trí đối tượng lớp python. Nó hoạt động giống như trong trường hợp hàm, ngoại trừ đối tượng được trang trí là một lớp . Bạn có thể đoán rằng trình trang trí mà bạn đang triển khai sẽ trả về một tham chiếu đến lớp có thứ tự cao hơn, sau đó.

Trang trí có thể được sử dụng trong lớp học?

Chúng ta có thể dễ dàng tạo các công cụ trang trí bên trong một lớp và nó có thể dễ dàng truy cập đối với các lớp con của nó.

Trình trang trí hoạt động như thế nào trong Python?

Decorators 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, trình trang trí là 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 .

Chủ Đề