Dekorator bisa menjadi topik yang menakutkan saat pertama kali ditemui. Sementara The Zen of Python menyatakan "Harus ada satu– dan sebaiknya hanya satu cara yang jelas untuk melakukannya", ada banyak cara yang sama validnya untuk mengimplementasikan dekorator yang sama. Metode yang berbeda ini dapat dikategorikan sebagai berbasis fungsi, berbasis kelas, atau campuran keduanya. Dalam posting ini saya akan menjelaskan desain dan perilaku dekorator Python dan memberikan contoh dekorator yang sering saya gunakan dalam kode saya sendiri Show
Apa itu Dekorator?Dalam Python, semuanya benar-benar objek, termasuk fungsi. Karena fungsi adalah objek, mereka dapat diteruskan sebagai argumen ke fungsi lain, mereka dapat menjadi nilai balik dari suatu fungsi, dan mereka dapat ditugaskan ke variabel. Jika Anda memahami konsep-konsep ini maka Anda memiliki semua yang Anda butuhkan untuk memahami dekorator Dekorator adalah objek yang dapat dipanggil yang mengambil fungsi sebagai parameter input. Saya secara khusus mengatakan "objek yang dapat dipanggil" daripada "fungsi" karena Python memungkinkan Anda membuat jenis objek yang dapat dipanggil lainnya. Fitur bahasa yang menarik inilah yang memungkinkan kita membuat dekorator berbasis kelas, seperti yang akan kita lihat sebentar lagi Dekorator SederhanaDekorator adalah pembungkus yang memungkinkan Anda mengeksekusi kode sebelum dan sesudah fungsi "dibungkus" (atau "dihiasi") dijalankan. Dengan membuat fungsi dekorator secara manual, efek "pembungkus" ini dapat dengan mudah didemonstrasikan. Pertimbangkan modul 6 yang diberikan di bawah ini
Buka shell Python interaktif dan jalankan 5 untuk melihat perilaku sebelum menerapkan dekorator apa pun. Selanjutnya, kami meneruskan _6 sebagai parameter ke 7, dan menyimpan nilai yang dikembalikan di 8
Harap perhatikan perbedaan antara memanggil fungsi ( 5) dan meneruskan fungsi sebagai parameter ke fungsi lain ( 0). Jika kita telah mengeksekusi _1, kita tidak akan melihat efek dari fungsi wrapper. Perilakunya akan sama seperti saat kita mengeksekusi 5Terakhir, kami mengeksekusi 3
Ini adalah hasil yang kami harapkan setelah menerapkan 7. Namun, bukankah lebih baik jika kita dapat mengubah perilaku ________9______6 secara permanen? _Inilah yang terjadi ketika Anda mendekorasi fungsi menggunakan sintaks 8 Python. Untuk memperkuat poin ini, kita dapat memodifikasi kode kita untuk menggunakan sintaks dekorator normal. Perhatikan bahwa kami menerapkan dekorator ke 6 di Baris 12
Mari kita verifikasi bahwa perilaku fungsi telah dimodifikasi
Seperti yang Anda lihat, _0 hanyalah gula sintaksis untuk 1Jenis dekorator ini bagus, tetapi bagaimana jika fungsi asli kita memiliki satu atau lebih parameter masukan? . Apa yang dapat kita lakukan untuk memperbaikinya? Meneruskan Argumen ke Fungsi TerbungkusMemperbaiki ini sangat mudah. Ingat, saat kita menjalankan fungsi "dibungkus", kita benar-benar menjalankan fungsi yang dikembalikan oleh fungsi dekorator ( 8 pada contoh sebelumnya). Nilai apa pun yang kami berikan ke fungsi ini dapat diteruskan ke fungsi yang dibungkusNamun, kami perlu mengakomodasi semua kemungkinan kombinasi parameter masukan. Kita dapat melakukan ini dengan memodifikasi _8 untuk menerima 5 dan meneruskannya ke 3. Ini telah diimplementasikan dalam modul baru, ________30______7
Mari kita uji versi ini dengan dua fungsi yang dihias, 8 dan 9 0Ini berfungsi persis seperti yang kita butuhkan, nilai yang kita berikan ke 9 digunakan karena itu diteruskan dari 8 ke 3. Selain itu, kami tidak merusak fungsionalitas yang ada karena fungsi yang tidak menggunakan parameter input apa pun ( 8) juga didekorasi dan berfungsi seperti yang diharapkanMeneruskan Argumen ke DekoratorDekorator yang telah kita buat sejauh ini tentu saja berguna untuk berbagai skenario, tetapi mereka juga terbatas karena tidak ada cara untuk menyampaikan argumen kepada dekorator itu sendiri. Apa bedanya dengan dekorator terakhir yang kita buat? 1Jika Anda ingat kembali ke awal posting ini, saya menyebutkan bahwa, secara umum, ada dua cara berbeda untuk mengimplementasikan dekorator Python. berbasis fungsi dan berbasis kelas. Contoh yang telah kita lihat sejauh ini semuanya berbasis fungsi. Kecuali jika Anda perlu membuat dekorator yang menerima argumen, Anda harus menggunakan desain berbasis fungsi ini karena lebih mudah dibaca dan membutuhkan lebih sedikit sarang/lekukan daripada desain berbasis kelas yang setara. Namun, saat Anda perlu meneruskan argumen ke dekorator, tidak ada keuntungan menggunakan desain berbasis fungsi atau berbasis kelas. Mari kita lihat desain berbasis fungsi terlebih dahulu karena ini merupakan perkembangan alami dari dekorator yang telah kita periksa Desain Berbasis FungsiBentuk generik dekorator berbasis fungsi yang menerima argumen diberikan di bawah ini 2 3Untuk meneruskan argumen ke dekorator, kami menambahkan fungsi pembungkus lain, yang disebut 4 (Baris 2). Saya menyebutnya pabrik karena nilai pengembalian adalah dekorator fungsi aktual ( 5 adalah tempat 3 diteruskan sebagai argumen)Untuk memahami cara kerjanya, Anda perlu menyadari bahwa Baris 15 (tempat kita menerapkan dekorator ke suatu fungsi) sebenarnya adalah . 5 adalah dekorator sebenarnya tetapi untuk meneruskan params "foo" dan "bar" ke dekorator, kami harus memanggil metode pabrik yang membuat dekorator aktual yang menerima fungsi 0 sebagai argumen dan membungkusnya. Bandingkan ini dengan dekorator lain yang telah kita buat. ketika suatu fungsi didekorasi dengan 0 atau 2 ini bukan pemanggilan fungsi (perhatikan bahwa tidak ada tanda kurung setelah nama dekorator). Mari jalankan REPL dan uji dekorator ini. Kami juga akan memverifikasi bahwa kami masih dapat menggunakan fungsi yang didekorasi seperti yang diharapkan dengan meneruskan argumen yang mengubah perilakunya _4Seperti yang Anda lihat, argumen yang diteruskan ke dekorator ( 3 dan 4) digunakan oleh fungsi pembungkus, dan nilai yang diteruskan ke fungsi yang didekorasi ( 5/ 6) juga digunakan saat fungsi pembungkus dijalankanFungsi, Kelas, dan CallableApakah Anda akrab dengan? . _9 jika objek yang diberikan tampaknya dapat dipanggil dan 0 jika tidak. Jika menurut Anda fungsi adalah satu-satunya "yang dapat dipanggil" yang ada, Anda mungkin menganggap fungsi ini agak tidak berguna atau tidak perlu. Namun, kelas juga dapat dipanggil karena ini adalah cara pembuatan instance baru (mis. g. , _1)Sintaks panggilan, 2, dapat memanggil fungsi atau membuat instance kelas seperti yang baru saja kita lihat. Tetapi Python memiliki fitur unik yang juga dapat memanggil objek selain fungsi. Menambahkan metode _3 ke kelas apa pun akan membuat instance dari kelas tersebut dapat dipanggil. Ini memungkinkan kita membuat dekorator yang diimplementasikan menggunakan kelasDesain Berbasis KelasDekorator yang sama dapat diimplementasikan menggunakan instance kelas yang dapat dipanggil
_6Perbedaan utama antara desain berbasis fungsi dan berbasis kelas adalah bagaimana argumen yang diteruskan ke dekorator ditangani. Dalam pendekatan berbasis fungsi, argumen tersedia untuk 8 sebagai variabel lokal. Dalam desain berbasis kelas, argumen diberikan ke metode 5 dan ditugaskan ke variabel instan yang dapat diakses dari 8Kami dapat memastikan bahwa dekorator ini berperilaku persis sama dengan versi berbasis fungsi 7Desain Mana yang Lebih Baik?Apakah ada keuntungan menggunakan salah satu desain dekorator? . Namun, saya mengakui bahwa desain berbasis fungsi lebih konvensional karena gagasan objek yang dapat dipanggil yang merupakan turunan dari kelas (bukan fungsi) bukanlah yang diharapkan kebanyakan orang ketika mereka menemukan konsep dekorator. Selain itu, tidak ada manfaat yang jelas untuk memilih satu desain dari yang lain. Anda harus menggunakan desain yang paling masuk akal bagi Anda Selalu Gunakan >>> decorated_function() Preparing to execute: undecorated_function I FORBID you from modifying how this function behaves! Finished executing: undecorated_function5Saya sengaja meninggalkan sesuatu yang sangat penting dari contoh dekorator ini. Anda harus SELALU menghias 8 (atau nama apa pun yang digunakan dalam aplikasi Anda) dengan dekorator 5 (terletak di modul 00 pustaka standar). Mengapa ini penting? _8Saat kami memeriksa nama dan tanda tangan fungsi 0, kami malah menerima nama dan tanda tangan dekorator yang diterapkan padanya. Meskipun membingungkan, akan lebih memusingkan jika Anda perlu men-debug kode ini. Ini mudah diperbaiki dengan dekorator _5 (Baris 2,11) 9 0Sekarang, jika kita memeriksa _0 kita akan melihat nama dan tanda tangan yang benar 1Mengapa saya tidak menyertakan dekorator 5 pada contoh sebelumnya? Mudah-mudahan Anda memiliki pemahaman yang lebih baik tentang bagaimana dekorator dirancang dan bagaimana perilakunya di Python. Sisa dari posting ini akan berisi contoh dekorator yang sering saya gunakan dalam proyek Python saya bersama dengan fungsi pytest yang menunjukkan penggunaan yang dimaksud Contoh. Batas Waktu FungsiJika Anda pernah menulis kode yang berinteraksi dengan layanan luar, Anda mungkin pernah mengalami situasi di mana program Anda terhenti menunggu respons tanpa ada cara untuk membatalkan pemanggilan fungsi. Salah satu cara untuk melepaskan diri adalah dengan dekorator 05 2 3Sintaks yang digunakan pada Baris 6 di atas mencegah pengguna menentukan argumen posisional dengan dekorator 05. Hal ini dilakukan untuk memastikan bahwa tujuan dekorator jelas bagi pembaca berdasarkan penggunaannya. Tanpa tanda bintang ( _07) dalam definisi fungsi, pengguna dapat menghias fungsi dengan 08, bukan 09. Penggunaan terakhir mengkomunikasikan arti dari nilai 10 dalam konteks dekorator 05. Jika Anda tidak terbiasa dengan sintaks ini, Anda dapat menemukan latar belakang dan pembenaran untuk fitur ini di PEP 3102Sangat mudah digunakan. Cukup hiasi fungsi apa saja dengan 12 dan tentukan jumlah detik untuk menunggu sebelum membatalkan pemanggilan fungsi seperti yang ditunjukkan di bawah ini (Baris 7). Jika fungsi selesai sebelum jumlah detik yang ditentukan berlalu, program Anda akan terus dijalankan. Namun jika fungsi belum selesai setelah jumlah detik yang ditentukan berlalu, 13 akan dimunculkan, membatalkan panggilan fungsiDalam skenario pengujian sederhana di bawah ini, fungsi _14 menunggu selama dua detik saat dipanggil. Karena dihiasi dengan 15 a 13 akan dinaikkan satu detik setelah disebut. Fungsi _17 memverifikasi bahwa kesalahan yang benar dimunculkan (Baris 13-14)
5Contoh. Coba Ulang FungsiContoh berikutnya mirip dengan dekorator _05 karena keduanya dirancang untuk menangani fungsi yang tidak dapat diandalkan. Dekorator _19 menambahkan logika coba lagi ke fungsi yang didekorasiUntuk menggunakannya, Anda menentukan satu set 20 yang dapat memicu percobaan yang gagal, jumlah percobaan yang gagal yang dapat terjadi sebelum membatalkan panggilan fungsi ( 21), jumlah detik penundaan setelah setiap percobaan yang gagal sebelum mencoba lagi ( 22) Definisi dekorator sebenarnya dimulai pada Baris 26 di bawah. Sebelum itu, Pengecualian khusus _23 didefinisikan (Baris 6-13). Ini adalah pengecualian yang muncul setelah _21 untuk memanggil fungsi telah gagal. Fungsi _25 (Baris 16-23) diberikan sebagai contoh dari apa yang dapat disediakan untuk parameter 19 dekorator 27 6 7Kita dapat menggunakan dekorator _05 untuk mendemonstrasikan dan menguji dekorator 19. Karena kita perlu mengetahui jenis _30 yang kita harapkan terjadi saat kita memanggil fungsi yang dihias, kita tentukan 31 karena ini adalah kesalahan yang diangkat oleh dekorator 05Dengan kode di bawah ini, kami akan mencoba memanggil 33 maksimal dua kali. Karena satu-satunya hal yang dilakukan fungsi ini adalah menunggu selama dua detik dan kita telah menghiasinya dengan 15, memanggilnya akan selalu memunculkan 13. Oleh karena itu, setelah upaya kedua yang gagal, dekorator _19 akan menaikkan 23Akhirnya, fungsi _38 memverifikasi bahwa 23 sebenarnya dimunculkan setelah memanggil fungsi 33 8 9Contoh. Log Tanda Tangan Panggilan dan Waktu EksekusiAplikasi dekorator yang paling umum mungkin adalah logging. Sangat mudah untuk mengetahui alasannya, memiliki kemampuan untuk menjalankan kode segera sebelum dan setelah suatu fungsi dipanggil memungkinkan Anda untuk melaporkan informasi dan menangkap metrik Dekorator ini menggunakan desain berbasis kelas, dan memungkinkan pengguna menyediakan logger khusus. Jika tidak ada yang tersedia, logger akan dibuat berdasarkan modul yang berisi fungsi yang dibungkus Setiap kali fungsi dipanggil, dekorator _41 menambahkan entri level 42 ke log dengan data berikut
0 1Kode di bawah menguji dekorator _41 dengan logger khusus dan dengan logger default. Dengan logger default, kami mengharapkan nama logger menjadi nama modul yang berisi fungsi yang didekorasi, 44 (Baris 30). Saat logger khusus disediakan, kami berharap namanya cocok dengan nilai yang kami tentukan saat logger dibuat, 45 (Baris 10, 38)Fitur yang bagus dari dekorator ini adalah tanda tangan panggilan fungsi berisi nama dan nilai dari semua argumen kata kunci, bahkan jika nilai default digunakan atau jika nama tidak diberikan saat panggilan terjadi. Misalnya, panggilan ke fungsi yang dihias pada Baris 28 adalah 46, tetapi tanda panggilan yang dicatat berisi nama ketiga argumen, 47 (Baris 32)Demikian pula, panggilan ke fungsi yang dihias di Baris 36 adalah 48, yang hanya menyediakan dua argumen. Tanda panggilan yang dicatat termasuk nilai default dari argumen yang hilang, 49 (Baris 40) 2 3Jika kita menjalankan 50 untuk contoh dekorator ini, semua tes lulus _4RingkasanJika Anda ingin mengunduh semua atau sebagian kode dari pos ini, Anda dapat dengan mudah melakukannya dari intisari Github yang ditautkan di bawah ini Dekorator Python Saya harap pengantar dekorator dengan Python ini membantu dan mudah dimengerti. Jika ada pertanyaan, kritik atau masukan silahkan tinggalkan komentar. terima kasih Bagaimana Anda mencetak nama fungsi dengan Python?Metode 1. Dapatkan Nama Fungsi dengan Python menggunakan function. nama_fungsi . Dengan menggunakan fungsi properti fungsi sederhana, func_name, seseorang bisa mendapatkan nama fungsi dan karenanya bisa sangat berguna untuk tujuan Pengujian dan juga untuk dokumentasi di waktu-waktu tertentu. Kekurangannya adalah ini hanya berfungsi untuk Python2.
Bagaimana Anda memanggil fungsi di dekorator?call() dekorator dengan Python
. Dekorator memungkinkan program dimodifikasi untuk menambahkan kode apa pun yang memiliki peran khusus untuk dimainkan. Dekorator dipanggil sebelum definisi fungsi yang telah Anda dekorasi. def dekorasi(fungsi).
Apa fungsi dekorator di Python?Dekorator adalah pola desain dalam Python yang memungkinkan pengguna menambahkan fungsionalitas baru ke objek yang sudah ada tanpa mengubah strukturnya . Dekorator biasanya dipanggil sebelum definisi fungsi yang ingin Anda hias.
Bagaimana cara menemukan nama string dalam suatu fungsi?Anda bisa mendapatkan nama fungsi sebagai string dengan menggunakan variabel __name__ khusus . |