Seorang dekorator mengambil suatu fungsi, menambahkan beberapa fungsi dan mengembalikannya. Dalam tutorial ini, Anda akan mempelajari cara membuat dekorator dan mengapa Anda harus menggunakannya.
Video:@Decorators dengan Python
Dekorator dengan Python
Python memiliki fitur menarik yang disebut dekorator untuk menambahkan fungsionalitas ke kode yang ada.
Ini juga disebut pemrograman meta karena bagian dari program mencoba untuk memodifikasi bagian lain dari program pada waktu kompilasi.
Prasyarat untuk belajar dekorator
Untuk memahami tentang dekorator, pertama-tama kita harus mengetahui beberapa hal dasar dalam Python.
Kita harus nyaman dengan kenyataan bahwa segala sesuatu di Python (Ya! Bahkan kelas), adalah objek. Nama yang kami definisikan hanyalah pengidentifikasi yang terikat pada objek ini. Fungsi tidak terkecuali, mereka juga objek (dengan atribut). Berbagai nama yang berbeda dapat diikat ke objek fungsi yang sama.
Ini contohnya.
def first(msg):
print(msg)
first("Hello")
second = first
second("Hello")
Keluaran
Hello
Hello
Saat Anda menjalankan kode, keduanya berfungsi first dan second memberikan keluaran yang sama. Di sini, nama first dan second merujuk ke objek fungsi yang sama.
Sekarang segalanya mulai menjadi lebih aneh.
Fungsi dapat diteruskan sebagai argumen ke fungsi lain.
Jika Anda telah menggunakan fungsi seperti map , filter dan reduce dengan Python, maka Anda sudah tahu tentang ini.
Fungsi seperti itu yang mengambil fungsi lain sebagai argumen juga disebut fungsi tingkat tinggi . Berikut adalah contoh 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.
Di sini, is_returned() adalah fungsi bersarang yang didefinisikan dan dikembalikan setiap kali kita memanggil is_called() .
Terakhir, kita harus tahu tentang Penutupan dengan Python.
Kembali ke Dekorator
Fungsi dan metode disebut dapat dipanggil begitu mereka bisa dipanggil.
Sebenarnya, objek apa pun yang mengimplementasikan __call__() special khusus metode ini disebut dapat dipanggil. Jadi, dalam pengertian yang paling dasar, dekorator adalah callable yang mengembalikan callable.
Pada dasarnya, seorang dekorator mengambil suatu fungsi, menambahkan beberapa fungsi dan mengembalikannya.
>>> ordinary()
I am ordinary
>>> # let's decorate this ordinary function
>>> pretty = make_pretty(ordinary)
>>> pretty()
I got decorated
I am ordinary
Pada contoh di atas, make_pretty() adalah seorang dekorator. Pada langkah penugasan:
pretty = make_pretty(ordinary)
Fungsi 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 hadiah. Dekorator bertindak sebagai pembungkus. Sifat objek yang didekorasi (hadiah sebenarnya di dalam) tidak berubah. Tapi sekarang, terlihat cantik (karena dihias).
Umumnya, kami mendekorasi sebuah fungsi dan menetapkannya kembali sebagai,
ordinary = make_pretty(ordinary).
Ini adalah konstruksi umum dan untuk alasan ini, Python memiliki sintaks untuk menyederhanakan ini.
Kita dapat menggunakan @ simbol beserta nama fungsi penghias dan letakkan di atas definisi fungsi yang akan dihias. Misalnya,
@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 mengimplementasikan dekorator.
Menghias Fungsi dengan Parameter
Dekorator di atas sederhana dan hanya berfungsi 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 ini akan memberikan kesalahan jika kami memasukkan 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 mengembalikan None jika 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 jeli akan melihat bahwa parameter dari inner() . bersarang fungsi di dalam dekorator sama dengan parameter fungsi yang dihiasnya. Dengan 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, args akan menjadi tupel argumen posisi dan kwargs akan 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
Merantai Dekorator 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.