Python Decorators: Bagaimana Cara Menggunakannya dan Mengapa?

Seorang dekorator mengambil fungsi, menambahkan beberapa fungsionalitas dan mengembalikannya. Dalam tutorial ini, Anda akan belajar bagaimana Anda bisa membuat dekorator dan mengapa Anda harus menggunakannya.

Dekorator dengan Python

Python memiliki fitur menarik yang disebut dekorator untuk menambahkan fungsionalitas ke kode yang sudah ada.

Ini juga disebut metaprogramming karena bagian dari program mencoba mengubah bagian lain dari program pada waktu kompilasi.

Prasyarat untuk dekorator belajar

Untuk memahami tentang dekorator, pertama-tama kita harus mengetahui beberapa hal dasar dalam Python.

Kita harus nyaman dengan fakta bahwa segala sesuatu di Python (Yes! Even class), adalah objek. Nama yang kami definisikan hanyalah pengenal yang terikat ke objek ini. Fungsi bukan pengecualian, mereka juga objek (dengan atribut). Berbagai nama berbeda dapat diikat ke objek fungsi yang sama.

Berikut ini contohnya.

 def first(msg): print(msg) first("Hello") second = first second("Hello")

Keluaran

 Halo Halo

Ketika Anda menjalankan kode, keduanya berfungsi firstdan secondmemberikan output yang sama. Di sini, nama firstdan secondmerujuk ke objek fungsi yang sama.

Sekarang hal-hal mulai menjadi lebih aneh.

Fungsi dapat diteruskan sebagai argumen ke fungsi lain.

Jika Anda pernah menggunakan fungsi like map, filterdan reducedengan Python, maka Anda sudah tahu tentang ini.

Fungsi yang mengambil fungsi lain sebagai argumen juga disebut fungsi tingkat tinggi . Berikut adalah contoh dari fungsi tersebut.

 def inc(x): return x + 1 def dec(x): return x - 1 def operate(func, x): result = func(x) return result

Kami memanggil fungsi sebagai berikut.

 >>> operate(inc,3) 4 >>> operate(dec,3) 2

Selanjutnya, suatu fungsi dapat mengembalikan fungsi lain.

 def is_called(): def is_returned(): print("Hello") return is_returned new = is_called() # Outputs "Hello" new()

Keluaran

 Halo

Di sini, is_returned()adalah fungsi bersarang yang didefinisikan dan dikembalikan setiap kali kita memanggil is_called().

Terakhir, kita harus tahu tentang Closures dengan Python.

Kembali ke Dekorator

Fungsi dan metode disebut dapat dipanggil karena keduanya dapat dipanggil.

Faktanya, objek apapun yang mengimplementasikan __call__()metode khusus disebut callable. Jadi, dalam pengertian paling dasar, dekorator adalah callable yang mengembalikan callable.

Pada dasarnya, dekorator mengambil fungsi, menambahkan beberapa fungsi, dan mengembalikannya.

 def make_pretty(func): def inner(): print("I got decorated") func() return inner def ordinary(): print("I am ordinary")

Saat Anda menjalankan kode berikut di shell,

 >>> ordinary() I am ordinary >>> # let's decorate this ordinary function >>> pretty = make_pretty(ordinary) >>> pretty() I got decorated I am ordinary

Pada contoh yang ditunjukkan di atas, make_pretty()adalah dekorator. Dalam langkah penugasan:

 pretty = make_pretty(ordinary)

Fungsi tersebut ordinary()didekorasi dan fungsi yang dikembalikan diberi nama pretty.

Kita dapat melihat bahwa fungsi dekorator menambahkan beberapa fungsi baru ke fungsi aslinya. Ini mirip dengan mengemas kado. Dekorator bertindak sebagai pembungkus. Sifat objek yang didekorasi (hadiah sebenarnya di dalam) tidak berubah. Tapi sekarang, terlihat cantik (karena didekorasi).

Umumnya, kami mendekorasi fungsi dan menetapkannya kembali sebagai,

 ordinary = make_pretty(ordinary).

Ini adalah konstruksi umum dan untuk alasan ini, Python memiliki sintaks untuk menyederhanakannya.

Kita bisa menggunakan @simbol beserta nama fungsi dekoratornya dan meletakkannya di atas definisi fungsi yang akan didekorasi. Sebagai contoh,

 @make_pretty def ordinary(): print("I am ordinary")

setara dengan

 def ordinary(): print("I am ordinary") ordinary = make_pretty(ordinary)

Ini hanyalah gula sintaksis untuk menerapkan dekorator.

Fungsi Dekorasi dengan Parameter

Dekorator di atas sederhana dan hanya bekerja dengan fungsi yang tidak memiliki parameter apa pun. Bagaimana jika kita memiliki fungsi yang mengambil parameter seperti:

 def divide(a, b): return a/b

Fungsi ini memiliki dua parameter, a dan b. Kami tahu itu akan memberikan kesalahan jika kami mengirimkan b sebagai 0.

 >>> divide(2,5) 0.4 >>> divide(2,0) Traceback (most recent call last):… ZeroDivisionError: division by zero

Sekarang mari kita buat dekorator untuk memeriksa kasus ini yang akan menyebabkan kesalahan.

 def smart_divide(func): def inner(a, b): print("I am going to divide", a, "and", b) if b == 0: print("Whoops! cannot divide") return return func(a, b) return inner @smart_divide def divide(a, b): print(a/b)

Implementasi baru ini akan kembali Nonejika kondisi kesalahan muncul.

 >>> divide(2,5) I am going to divide 2 and 5 0.4 >>> divide(2,0) I am going to divide 2 and 0 Whoops! cannot divide

Dengan cara ini, kita dapat mendekorasi fungsi yang mengambil parameter.

Seorang pengamat yang tajam akan melihat bahwa parameter dari inner()fungsi yang disarangkan di dalam dekorator sama dengan parameter fungsi yang didekorasi. Mempertimbangkan hal ini, sekarang kita dapat membuat dekorator umum yang bekerja dengan sejumlah parameter.

Dengan Python, keajaiban ini dilakukan sebagai function(*args, **kwargs). Dengan cara ini, argsakan menjadi tupel argumen posisi dan kwargsakan menjadi kamus argumen kata kunci. Contoh dekorator seperti itu adalah:

 def works_for_all(func): def inner(*args, **kwargs): print("I can decorate any function") return func(*args, **kwargs) return inner

Dekorator Rantai dengan Python

Beberapa dekorator dapat dirantai dengan Python.

Artinya, suatu fungsi dapat didekorasi beberapa kali dengan dekorator yang berbeda (atau sama). Kami cukup menempatkan dekorator di atas fungsi yang diinginkan.

 def star(func): def inner(*args, **kwargs): print("*" * 30) func(*args, **kwargs) print("*" * 30) return inner def percent(func): def inner(*args, **kwargs): print("%" * 30) func(*args, **kwargs) print("%" * 30) return inner @star @percent def printer(msg): print(msg) printer("Hello")

Keluaran

 ****************************** %%%%%%%%%%%%%%%%%%% %%%%%%%%%% Hello %%%%%%%%%%%%%%%%%%%%%%%%%%%%% ********* *********************

Sintaks di atas dari,

 @star @percent def printer(msg): print(msg)

setara dengan

 def printer(msg): print(msg) printer = star(percent(printer))

Urutan di mana kita rantai dekorator penting. Jika kami membalik urutannya sebagai,

 @percent @star def printer(msg): print(msg)

Outputnya adalah:

 %%%%%%%%%%%%%%%%%%%%%%%%%%%%% ******************** ********** Halo ****************************** %%%%%%%% %%%%%%%%%%%%%%%%%%%%

Artikel yang menarik...