Decorator

Pada artikel ini, kita akan mempelajari perihal decorator, cara membuat decorator, dan kapan kita sebaiknya menggunakan decorator.



 



Tabel Konten









Pengertian Decorator



Python memiliki sebuah fitur menarik bernama decorator yang berfungsi menambah fungsionalitas pada arahan program.



Hal ini disebut juga metaprogramming alasannya ada pecahan dari acara yang mencoba untuk memodifikasi pecahan lainnya pada dikala eksekusi.







Syarat Sebelum Mempelajari Decorator



Sebelum mampu memahami perihal decorator, kita harus terlebih dahulu memahami dasar – dasar Python.



Kita harus paham terlebih dahulu bahwa semua yang ada di Python yaitu objek (termasuk kelas). Nama pengenal, mirip variabel yang kita deklarasikan merujuk kepada objek tersebut. Begitu juga dengan fungsi. Fungsi yaitu termasuk objek juga. Satu objek mampu memiliki banyak pengenal (identifier) yang merujuk kepadanya.



Perhatikan pola berikut



 
def first(msg):
print(msg)


first("Hello")
second = first
second("Hello")


Pada dikala arahan di atas dijalankan, kedua fungsi first dan second menampilkan output yang sama. Di sini, variabel first dan second merujuk pada objek fungsi yang sama.



Sekarang mari kita tinjau hal yang lain. Sebuah fungsi mampu dijadikan sebagai argumen dari fungsi yang lain.



Bila Anda sudah pernah menggunakan fungsi mirip map, filter, dan reduce di Python, maka Anda sudah tahu perihal hal ini.



Fungsi yang menjadikan fungsi lain sebagai argumen disebut juga fungsi dengan orde yang lebih tinggi. Berikut yaitu contohnya:




def inc(x):
return x + 1


def dec(x):
return x - 1


def operate(func, x):
result = func(x)
return result



Kita mampu memanggil fungsi tersebut mirip berikut:



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


Lebih lanjut lagi, sebuah fungsi mampu mengembalikan fungsi lain.




def is_called():
def is_returned():
print("Hello")
return is_returned


new = is_called()
#Outputs "Hello"
new()



Pada pola tersebut, is_returned() yaitu fungsi bersarang yang didefinisikan dan dikembalikan tiap kali fungsi is_called() dipanggil.



Selain memahami perihal hal di atas, kita juga sudah harus paham perihal python closure







Kembali ke Decorator



Sebuah decorator mengambil fungsi sebagai argumennya, menambahkan beberapa hal, dan kemudian mengembalikannya.




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


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



Bila arahan di atas kita jalankan pada mode interaktif, maka jadinya yaitu mirip berikut:



>>> ordinary()
I am ordinary

>>> # Mari kita buat decorator dari fungsi ordinary
>>> pretty = make_pretty(ordinary)
>>> pretty()
I got decorated
I am ordinary


Pada pola di atas, make_pretty() yaitu sebuah decorator.



Pada baris perintah pretty = make_pretty(ordinary), fungsi ordinary didekorasi dan fungsi kembaliannya diberi nama pretty.



Kita mampu lihat bahwa fungsi decorator menambahkan beberapa fungsionalitas ke fungsi asli. Hal ini mirip dengan pengemasan kado. Decorator bertindak sebagai bungkusnya. Objek yang didekorasi (isi kado) tidak berubah. Akan tetapi, saat dibungkus, akan terlihat lebih bagus (karena didekorasi).



Umumnya, kita mendekorasi fungsi dan menyimpannya ke variabel mirip berikut:



ordinary = make_pretty(ordinary)


Python memiliki sintaks yang lebih sederhana untuk penulisan fungsi di atas yaitu dengan menggunakan tanda  @ diikuti oleh nama fungsi decorator. Kita menempatkannya di atas fungsi yang akan didekorasi. Maka pola berikut ini:



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


adalah sama dengan yang berikut:



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


Cara yang menggunakan tanda @ di atas yaitu sintaks yang lebih elegan untuk mengimplementasikan decorator.







Dekorasi Fungsi Dengan Parameter



Decorator di atas sangat sederhana dan hanya berlaku untuk fungsi yang tidak memiliki parameter. Bagaimana jikalau fungsi yang akan didekorasi memiliki argumen mirip berikut?



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


Fungsi tersebut memiliki 2 parameter, a dan b. Bila kita melewatkan nilai 0 ke b, maka akan terjadi error ZeroDivisionError.



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


Sekarang kita akan membuat decorator untuk mengecek penyebab error ini.



 
def smart_divide(func):
def inner(a,b):
print("Saya akan membagi",a,"dan",b)
if b == 0:
print("Whoops! tidak mampu membagi dengan 0")
return


return func(a,b)
return inner


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


Kode yang menggunakan decorator ini akan mengembalikan None jikalau terjadi error.



>>> divide(2, 5)
Saya akan membagi 2 dan 5
0.4

>>> divide(2, 0)
Saya akan membagi 2 dan 0
Whoops! tidak mampu membagi dengan 0


Dengan cara tersebut kita mampu mendekorasi fungsi yang memiliki parameter.



Bila kita perhatikan dengan baik, kita akan melihat kalau semua parameter dari fungsi yang di dalam decorator akan menjadi parameter dari fungsi yang didekorasi. Dengan itu, kita mampu membuat decorator yang lebih umum yang mampu bekerja dengan berapapun jumlah parameternya.



Di Python, hal ini mampu dilakukan dengan sintaks function(*args, **kwargs) di mana args yaitu tuple dari argumen – argumen berdasarkan posisi, dan kwargs yaitu dictionary dari argumen – argumen ber-keyword.



Berikut ini yaitu pola fungsi inner() yang memiliki sembarang parameter didekorasi oleh fungsi works_for_all().



def works_for_all(func):
def inner(*args, **kwargs):
print("Saya mampu mendekorasi fungsi apa saja")
return func(*args, **kwargs)
return inner()






Menggabungkan Decorator di Python



Beberapa decorator mampu dihubungkan atau digabungkan. Sebuah fungsi mampu didekorasi beberapa kali dengan satu atau beberapa fungsi decorator. Kita meletakkan decorator di atas fungsi yang akan didekorasi. Untuk jelasnya perhatikan pola berikut:



 
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")



Outputnya akan tampak mirip berikut:



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


 



Kode decorator di atas yaitu:



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


adalah sama dengan:



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


 



Urutan dari decorator perlu diperhatikan. Bila kita mengubah urutannya menjadi:



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


maka jadinya akan menjadi:



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


 



Popular posts from this blog

Subitems Listview Berwarna Selang Seling

Source Code Aplikasi Tagihan Internet Memakai Php