Trình trang trí trong Python với ví dụ w3schools là gì?
Trình trang trí có lẽ thuộc về khả năng thiết kế đẹp nhất và mạnh mẽ nhất trong Python, nhưng đồng thời, khái niệm này được nhiều người coi là phức tạp để tiếp cận. Nói một cách chính xác, việc sử dụng các bộ trang trí rất dễ dàng, nhưng việc viết các bộ trang trí có thể phức tạp, đặc biệt nếu bạn chưa có kinh nghiệm với các bộ trang trí và một số khái niệm lập trình chức năng Show
Mặc dù có cùng một khái niệm cơ bản, nhưng chúng ta có hai loại trình trang trí khác nhau trong Python
Trình trang trí trong Python là bất kỳ đối tượng Python có thể gọi nào được sử dụng để sửa đổi hàm hoặc lớp. Một tham chiếu đến hàm "func" hoặc lớp "C" được chuyển đến trình trang trí và trình trang trí trả về hàm hoặc lớp đã sửa đổi. Các chức năng hoặc lớp được sửa đổi thường chứa các cuộc gọi đến chức năng ban đầu "func" hoặc lớp "C" Bạn cũng có thể tham khảo chương của chúng tôi về ghi nhớ với trang trí Nếu bạn thích hình ảnh ở phía bên phải của trang này và nếu bạn cũng quan tâm đến việc xử lý hình ảnh bằng Python, Numpy, Scipy và Matplotlib, thì chắc chắn bạn sẽ thích chương của chúng tôi về Kỹ thuật xử lý hình ảnh, nó giải thích toàn bộ quá trình tạo- Đào tạo Python trực tiếp Thưởng thức trang này? Thấy. Tổng quan về các khóa học Python trực tiếp đăng ký tại đây Những bước đầu tiên để trang tríChúng tôi biết từ các lớp đào tạo Python khác nhau của mình rằng có một số điểm trong định nghĩa về trình trang trí khiến nhiều người mới bắt đầu gặp khó khăn Do đó, chúng tôi sẽ giới thiệu các bộ trang trí bằng cách lặp lại một số khía cạnh quan trọng của chức năng. Trước tiên, bạn phải biết hoặc nhớ rằng tên hàm là tham chiếu đến hàm và chúng ta có thể gán nhiều tên cho cùng một hàm def succ(x): return x + 1 successor = succ successor(10) ĐẦU RA11 succ(10) ĐẦU RA11 Điều này có nghĩa là chúng tôi có hai tên, tôi. e. "succ" và "successor" cho cùng chức năng. Thực tế quan trọng tiếp theo là chúng ta có thể xóa "succ" hoặc "successor" mà không xóa chính chức năng đó del succ successor(10) ĐẦU RA11 Các chức năng bên trong Chức năngKhái niệm có hoặc định nghĩa hàm bên trong hàm là hoàn toàn mới đối với lập trình viên C hoặc C++ def f(): def g(): print("Hi, it's me 'g'") print("Thanks for calling me") print("This is the function 'f'") print("I am calling 'g' now:") g() f() ĐẦU RAThis is the function 'f' I am calling 'g' now: Hi, it's me 'g' Thanks for calling me Một ví dụ khác sử dụng các câu lệnh trả về "thích hợp" trong các hàm ________số 8_______ ĐẦU RAIt's 68.0 degrees! Ví dụ sau đây là về hàm giai thừa, mà trước đây chúng ta đã định nghĩa như sau 110 Điều gì xảy ra nếu ai đó chuyển một giá trị âm hoặc số float cho hàm này? . Bạn có thể có ý tưởng để kiểm tra như sau 111 Ví dụ, nếu bạn gọi hàm này bằng def temperature(t): def celsius2fahrenheit(x): return 9 * x / 5 + 32 result = "It's " + str(celsius2fahrenheit(t)) + " degrees!" return result print(temperature(20))8, tôi. e. def temperature(t): def celsius2fahrenheit(x): return 9 * x / 5 + 32 result = "It's " + str(celsius2fahrenheit(t)) + " degrees!" return result print(temperature(20))9, điều đầu tiên được kiểm tra là liệu đó có phải là số nguyên dương của tôi không. Về nguyên tắc, điều này có ý nghĩa. "Sự cố" hiện xuất hiện trong bước đệ quy. Bây giờ It's 68.0 degrees!0 được gọi. Cuộc gọi này và tất cả những cuộc gọi khác cũng kiểm tra xem đó có phải là số nguyên dương hay không. Nhưng điều này là không cần thiết. Nếu bạn trừ đi giá trị It's 68.0 degrees!1 từ một số nguyên dương, bạn sẽ nhận được một số nguyên dương hoặc lại là It's 68.0 degrees!2. Vì vậy, cả hai giá trị đối số được xác định rõ ràng cho chức năng của chúng tôi Với một hàm lồng nhau (hàm cục bộ), người ta có thể giải quyết vấn đề này một cách tao nhã 112 Chúng ta có thể mở rộng miền giá trị đầu vào có thể có cho hàm It's 68.0 degrees!3 của mình bằng cách cho phép các số float tương đương với số nguyên, i. e. thỏa mãn điều kiện int(x) == x. Nếu chúng ta biết rằng một biến x tham chiếu đến một giá trị float, chúng ta cũng có thể sử dụng phép thử x. is_integer() Việc triển khai giai thừa sau đây tuân theo phân tích trường hợp chi tiết hơn về đối số như đã thảo luận trước đây 113 Hãy để chúng tôi kiểm tra chức năng trước đó 114 ĐẦU RA115 Chức năng như tham sốNếu bạn chỉ nhìn vào các ví dụ trước, điều này dường như không hữu ích lắm. Nó trở nên hữu ích khi kết hợp với hai khả năng mạnh mẽ hơn nữa của các hàm Python. Do thực tế là mọi tham số của một hàm là một tham chiếu đến một đối tượng và các hàm cũng là các đối tượng, chúng ta có thể chuyển các hàm - hay tốt hơn là "các tham chiếu đến các hàm" - làm tham số cho một hàm. Chúng tôi sẽ chứng minh điều này trong ví dụ đơn giản tiếp theo 116 ĐẦU RA117 Bạn có thể không hài lòng với đầu ra. 'f' nên viết rằng nó gọi là 'g' chứ không phải 'func'. Tất nhiên, chúng ta cần biết tên 'thật' của func là gì. Với mục đích này, chúng ta có thể sử dụng thuộc tính It's 68.0 degrees!4, vì nó chứa tên này 118 ĐẦU RA119 Đầu ra giải thích những gì đang xảy ra một lần nữa. Một vi dụ khac succ(10)0 ĐẦU RAsucc(10)1 Hàm trả về HàmĐầu ra của một chức năng cũng là một tham chiếu đến một đối tượng. Do đó, các hàm có thể trả về các tham chiếu đến các đối tượng hàm succ(10)2 ĐẦU RAsucc(10)3 Ví dụ trước trông rất giả tạo và hoàn toàn vô dụng. Bây giờ chúng tôi sẽ trình bày một ví dụ định hướng ngôn ngữ khác, cho thấy một liên lạc thực tế hơn. Được rồi, vẫn không phải là một chức năng hữu ích theo cách của nó. Chúng tôi viết một chức năng với tên gần như tự giải thích It's 68.0 degrees!5. Vì vậy, hàm này trả về (hoặc tạo) các hàm có thể được sử dụng để tạo người ở các ngôn ngữ khác nhau, tôi. e. Đức, Pháp, Ý, Thổ Nhĩ Kỳ và Hy Lạp succ(10)4 ĐẦU RAsucc(10)5 Một ví dụ hữu ích hơnNó trở nên hữu ích hơn và đồng thời được định hướng toán học hơn trong ví dụ sau. Giả sử ta phải xác định nhiều đa thức bậc 2. Nó có thể trông như thế này succ(10)6 Điều này có thể được đơn giản hóa bằng cách triển khai hàm "nhà máy" đa thức ngay bây giờ. Chúng ta sẽ bắt đầu với việc viết một phiên bản có thể tạo đa thức bậc 2 $$p(x) = ax^2 + bx + c$$ Việc triển khai Python dưới dạng hàm nhà máy đa thức có thể được viết như thế này succ(10)7 ĐẦU RAsucc(10)8 Chúng ta có thể khái quát hóa hàm xuất xưởng của mình để nó có thể hoạt động đối với các đa thức có bậc tùy ý $$\sum_{k=0}^{n} a_{k} \cdot x^{k} = a_{n} \cdot x^{n} + a_{n-1} \cdot x^{n- . + a_{2} \cdot x^{2} + a_{1} \cdot x + a_{0} $$ succ(10)9 ĐẦU RA110 Ví dụ, hàm p3 thực hiện đa thức sau $$p_3(x) = x^{5} + 8 \cdot x^{4} - x^{3} + 3 \cdot x + 2 $$ Chức năng đa thức bên trong polynomial_creator trang trí của chúng tôi có thể được triển khai hiệu quả hơn. Chúng ta có thể phân tích thành thừa số theo cách mà nó không cần bất kỳ phép lũy thừa nào Phiên bản thừa số của đa thức tổng quát mà không có lũy thừa $$res = (. (a_{n} \cdot x + a_{n-1}) \cdot x +. + a_{1}) \cdot x + a_{0}$$ Triển khai trình tạo trang trí đa thức của chúng tôi để tránh lũy thừa 111 ĐẦU RA110 Nếu bạn muốn tìm hiểu thêm về đa thức và cách tạo một hạng tử của đa thức, bạn có thể tiếp tục với chương của chúng tôi về Đa thức Đào tạo Python trực tiếp Thưởng thức trang này? Thấy. Tổng quan về các khóa học Python trực tiếp Các khóa học trực tuyến sắp tới Khóa học nâng cao chuyên sâu Python dành cho kỹ sư và nhà khoa học đăng ký tại đây Một trang trí đơn giảnBây giờ chúng tôi đã có mọi thứ sẵn sàng để xác định trình trang trí đơn giản đầu tiên của chúng tôi 113 ĐẦU RA114 Nếu bạn nhìn vào đầu ra của chương trình trước, bạn có thể thấy điều gì đang xảy ra. Sau phần trang trí "foo = our_decorator(foo)", foo là tham chiếu đến 'function_wrapper'. 'foo' sẽ được gọi bên trong 'function_wrapper', nhưng trước và sau khi gọi, một số mã bổ sung sẽ được thực thi, tôi. e. trong trường hợp của chúng tôi, hai chức năng in Cú pháp thông thường cho Trình trang trí trong PythonPhần trang trí trong Python thường không được thực hiện theo cách chúng ta đã làm trong ví dụ trước, mặc dù ký hiệu It's 68.0 degrees!6 rất hấp dẫn và dễ nắm bắt. Đây là lý do, tại sao chúng tôi sử dụng nó. Bạn cũng có thể thấy một vấn đề thiết kế trong cách tiếp cận trước đây của chúng tôi. "foo" tồn tại trong cùng một chương trình ở hai phiên bản, trước khi trang trí và sau khi trang trí Bây giờ chúng ta sẽ trang trí thích hợp. Trang trí xảy ra trong dòng trước tiêu đề chức năng. "@" được theo sau bởi tên chức năng trang trí Bây giờ chúng tôi sẽ viết lại ví dụ ban đầu của chúng tôi. Thay vì viết tuyên bố 115 chúng tôi có thể viết 116Nhưng dòng này phải được đặt ngay trước chức năng được trang trí. Ví dụ hoàn chỉnh trông như thế này bây giờ 117 ĐẦU RA118 Chúng tôi có thể trang trí mọi chức năng khác có một tham số với trình trang trí 'our_decorator' của chúng tôi. Chúng tôi chứng minh điều này trong phần sau. Chúng tôi đã thay đổi một chút trình bao hàm của mình để chúng tôi có thể thấy kết quả của các lệnh gọi hàm 119 ĐẦU RAdel succ successor(10)0 Cũng có thể trang trí các chức năng của bên thứ ba, e. g. các chức năng chúng tôi nhập từ một mô-đun. Chúng ta không thể sử dụng cú pháp Python có dấu "at" trong trường hợp này del succ successor(10)1 ĐẦU RAdel succ successor(10)2 Đào tạo Python trực tiếp Thưởng thức trang này? Thấy. Tổng quan về các khóa học Python trực tiếp đăng ký tại đây Mở rộng hàm lượng giác của toán họcHãy để chúng tôi tạo một trình trang trí hữu ích hơn cho các hàm lượng giác. Nếu bạn xem phần trợ giúp của It's 68.0 degrees!7, It's 68.0 degrees!8 hoặc các hàm lượng giác khác của mô-đun toán học, bạn sẽ thấy rằng các đối số của to là giá trị rad. Nếu bạn thích sử dụng độ thì sao? del succ successor(10)3 ĐẦU RAdel succ successor(10)4 del succ successor(10)5 ĐẦU RAdel succ successor(10)6 Bây giờ, chúng ta có thể áp dụng giá trị cho It's 68.0 degrees!7 hoặc các hàm lượng giác khác del succ successor(10)7 ĐẦU RAdel succ successor(10)8Chúng ta cũng có thể mở rộng các hàm lượng giác bằng một công cụ trang trí, tự động biến độ thành giá trị radian. Chúng tôi thêm một tham số khác vào các chức năng del succ successor(10)9 110 ĐẦU RA111 Nói chung, chúng ta có thể nói rằng một trình trang trí trong Python là một đối tượng Python có thể gọi được, được sử dụng để sửa đổi một hàm, phương thức hoặc định nghĩa lớp. Đối tượng ban đầu, đối tượng sẽ được sửa đổi, được chuyển đến trình trang trí làm đối số. Trình trang trí trả về một đối tượng đã sửa đổi, e. g. một hàm đã sửa đổi, được liên kết với tên được sử dụng trong định nghĩa Hàm_wrapper trước chỉ hoạt động đối với các hàm có chính xác một tham số. Chúng tôi cung cấp một phiên bản tổng quát của function_wrapper, phiên bản này chấp nhận các hàm có tham số tùy ý trong ví dụ sau 112 ĐẦU RA113 Sử dụng nhiều trang tríCó thể trang trí các chức năng với nhiều hơn một trình trang trí 114 ĐẦU RA115 Đầu ra cho chúng ta thấy rằng chức năng 1100 được trang trí đầu tiên với 1101, i. e. trình trang trí trực tiếp trên định nghĩa hàm. Sau đó, nó được trang trí bằng 1102 và hơn nữa là 1103 Khi chúng ta gọi chức năng trang trí nhiều lần, nó hoạt động theo cách khác 116 ĐẦU RA117 Đào tạo Python trực tiếp Thưởng thức trang này? Thấy. Tổng quan về các khóa học Python trực tiếp đăng ký tại đây Các trường hợp sử dụng cho người trang tríKiểm tra các đối số với một DecoratorTrong chương về hàm đệ quy, chúng ta đã giới thiệu hàm giai thừa. Chúng tôi muốn giữ chức năng đơn giản nhất có thể và chúng tôi không muốn che khuất ý tưởng cơ bản, vì vậy chúng tôi đã không kết hợp bất kỳ kiểm tra đối số nào. Vì vậy, nếu ai đó gọi hàm của chúng ta bằng đối số phủ định hoặc bằng đối số float, thì hàm của chúng ta sẽ rơi vào vòng lặp vô tận Chương trình sau sử dụng hàm trang trí để đảm bảo rằng đối số được truyền cho hàm giai thừa là một số nguyên dương 118 ĐẦU RA119 Đếm lời gọi hàm với DecoratorsVí dụ sau sử dụng một trình trang trí để đếm số lần một hàm được gọi. Nói chính xác, chúng ta chỉ có thể sử dụng trình trang trí này cho các hàm có chính xác một tham số def f(): def g(): print("Hi, it's me 'g'") print("Thanks for calling me") print("This is the function 'f'") print("I am calling 'g' now:") g() f()0 ĐẦU RAdef f(): def g(): print("Hi, it's me 'g'") print("Thanks for calling me") print("This is the function 'f'") print("I am calling 'g' now:") g() f()1 Chúng tôi đã chỉ ra rằng chúng tôi chỉ có thể sử dụng trình trang trí trước đó cho các hàm nhận chính xác một tham số. Chúng tôi sẽ sử dụng ký hiệu *args và **kwargs để viết các trình trang trí có thể xử lý các hàm có số lượng tham số vị trí và từ khóa tùy ý def f(): def g(): print("Hi, it's me 'g'") print("Thanks for calling me") print("This is the function 'f'") print("I am calling 'g' now:") g() f()2 ĐẦU RAdef f(): def g(): print("Hi, it's me 'g'") print("Thanks for calling me") print("This is the function 'f'") print("I am calling 'g' now:") g() f()3 Trang trí với các tham sốChúng tôi xác định hai trang trí trong đoạn mã sau def f(): def g(): print("Hi, it's me 'g'") print("Thanks for calling me") print("This is the function 'f'") print("I am calling 'g' now:") g() f()4 ĐẦU RAdef f(): def g(): print("Hi, it's me 'g'") print("Thanks for calling me") print("This is the function 'f'") print("I am calling 'g' now:") g() f()5 Hai trang trí này gần giống nhau, ngoại trừ lời chào. Chúng tôi muốn thêm một tham số để trình trang trí có thể tùy chỉnh lời chào khi chúng tôi thực hiện trang trí. Chúng ta phải bọc một chức năng khác xung quanh chức năng trang trí trước đó của mình để thực hiện điều này. Bây giờ chúng ta có thể dễ dàng nói "Chào buổi sáng" bằng tiếng Hy Lạp def f(): def g(): print("Hi, it's me 'g'") print("Thanks for calling me") print("This is the function 'f'") print("I am calling 'g' now:") g() f()6 ĐẦU RAdef f(): def g(): print("Hi, it's me 'g'") print("Thanks for calling me") print("This is the function 'f'") print("I am calling 'g' now:") g() f()7 Nếu chúng ta không muốn hoặc không thể sử dụng cú pháp trang trí "at", chúng ta có thể thực hiện điều đó bằng các lệnh gọi hàm def f(): def g(): print("Hi, it's me 'g'") print("Thanks for calling me") print("This is the function 'f'") print("I am calling 'g' now:") g() f()8 ĐẦU RAdef f(): def g(): print("Hi, it's me 'g'") print("Thanks for calling me") print("This is the function 'f'") print("I am calling 'g' now:") g() f()7 Tất nhiên, chúng tôi không cần định nghĩa bổ sung về "lời chào2". Chúng ta có thể áp dụng trực tiếp kết quả của lệnh gọi "greeting("καλημερα")" trên "foo" This is the function 'f' I am calling 'g' now: Hi, it's me 'g' Thanks for calling me0 Đào tạo Python trực tiếp Thưởng thức trang này? Thấy. Tổng quan về các khóa học Python trực tiếp đăng ký tại đây Sử dụng kết thúc tốt đẹp từ funcoolsCách chúng ta định nghĩa các decorator cho đến nay vẫn chưa tính đến việc các thuộc tính
của các chức năng ban đầu sẽ bị mất sau khi trang trí This is the function 'f' I am calling 'g' now: Hi, it's me 'g' Thanks for calling me1 Chúng tôi gọi nó trong chương trình sau This is the function 'f' I am calling 'g' now: Hi, it's me 'g' Thanks for calling me2 ĐẦU RAThis is the function 'f' I am calling 'g' now: Hi, it's me 'g' Thanks for calling me3 Ta được kết quả "không mong muốn" ở trên Chúng ta có thể lưu các thuộc tính ban đầu của hàm f, nếu chúng ta gán chúng bên trong bộ trang trí. Chúng tôi thay đổi trang trí trước đó của chúng tôi cho phù hợp This is the function 'f' I am calling 'g' now: Hi, it's me 'g' Thanks for calling me4 This is the function 'f' I am calling 'g' now: Hi, it's me 'g' Thanks for calling me2 ĐẦU RAThis is the function 'f' I am calling 'g' now: Hi, it's me 'g' Thanks for calling me6 May mắn thay, chúng tôi không phải thêm tất cả mã này vào bộ trang trí của mình để có những kết quả này. Thay vào đó, chúng ta có thể nhập "các gói" trang trí từ functools và trang trí chức năng của chúng ta trong trình trang trí với nó This is the function 'f' I am calling 'g' now: Hi, it's me 'g' Thanks for calling me7 This is the function 'f' I am calling 'g' now: Hi, it's me 'g' Thanks for calling me2 ĐẦU RAThis is the function 'f' I am calling 'g' now: Hi, it's me 'g' Thanks for calling me6 Các lớp thay vì Chức năngphương pháp cuộc gọiCho đến nay chúng tôi đã sử dụng các chức năng như trang trí. Trước khi chúng ta có thể định nghĩa một trình trang trí là một lớp, chúng ta phải giới thiệu phương thức lớp 1107. Chúng tôi đã đề cập rằng một trình trang trí chỉ đơn giản là một đối tượng có thể gọi được, lấy một hàm làm tham số đầu vào. Một hàm là một đối tượng có thể gọi được, nhưng nhiều lập trình viên Python không biết rằng có những đối tượng có thể gọi được khác. Một đối tượng có thể gọi được là một đối tượng có thể được sử dụng và hoạt động như một hàm nhưng có thể không phải là một hàm. Có thể định nghĩa các lớp theo cách mà các thể hiện sẽ là các đối tượng có thể gọi được. Phương thức 1107 được gọi, nếu thể hiện được gọi là "giống như một hàm", tôi. e. sử dụng dấu ngoặc def temperature(t): def celsius2fahrenheit(x): return 9 * x / 5 + 32 result = "It's " + str(celsius2fahrenheit(t)) + " degrees!" return result print(temperature(20))0 ĐẦU RAdef temperature(t): def celsius2fahrenheit(x): return 9 * x / 5 + 32 result = "It's " + str(celsius2fahrenheit(t)) + " degrees!" return result print(temperature(20))1 Chúng ta có thể viết một lớp cho hàm fibonacci bằng cách sử dụng phương thức 1107 def temperature(t): def celsius2fahrenheit(x): return 9 * x / 5 + 32 result = "It's " + str(celsius2fahrenheit(t)) + " degrees!" return result print(temperature(20))2 ĐẦU RAdef temperature(t): def celsius2fahrenheit(x): return 9 * x / 5 + 32 result = "It's " + str(celsius2fahrenheit(t)) + " degrees!" return result print(temperature(20))3 Bạn có thể tìm thêm thông tin về phương pháp 1107 trong chương Hàm ma thuật của hướng dẫn của chúng tôi Trình trang trí Python và ví dụ là gì?Trình trang trí là mẫu thiết kế trong Python cho phép người dùng thêm chức năng mới vào đối tượng hiện có mà không sửa đổi cấu trúc của đối tượng . Trình trang trí thường được gọi trước khi định nghĩa chức năng bạn muốn trang trí.
Có gì trong trình trang trí Python?Trình trang trí trong Python là hàm nhận một hàm khác làm đối số và trả về một hàm khác . Trình trang trí có thể cực kỳ hữu ích vì chúng cho phép mở rộng chức năng hiện có mà không có bất kỳ sửa đổi nào đối với mã nguồn của chức năng ban đầu.
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.
Trang trí trong Python với các câu hỏi phỏng vấn ví dụ là gì?Khi chúng tôi nhắc đến từ "trang trí", bạn nghĩ đến điều gì? . Một ví dụ là khi chúng ta treo một khung tranh vào tường để làm nổi bật căn phòng. Trình trang trí trong Python thêm một số tính năng hoặc chức năng vào chức năng hiện có mà không thay đổi chức năng đó . |