Python Decorators: Bagaimana Menggunakannya dan Mengapa?

Penghias menggunakan fungsi, menambah beberapa fungsi dan mengembalikannya. Dalam tutorial ini, anda akan belajar bagaimana anda boleh membuat penghias dan mengapa anda harus menggunakannya.

Penghias di Python

Python mempunyai ciri menarik yang disebut sebagai penghias untuk menambahkan fungsi pada kod yang ada.

Ini juga disebut pemrograman metaprogram kerana sebahagian daripada program cuba mengubah bahagian program yang lain pada waktu kompilasi.

Prasyarat untuk belajar penghias

Untuk memahami mengenai penghias, kita mesti mengetahui beberapa perkara asas di Python.

Kita mesti merasa selesa dengan kenyataan bahawa segala sesuatu di Python (Ya! Malah kelas), adalah objek. Nama yang kita tentukan hanyalah pengecam yang terikat pada objek ini. Fungsi tidak terkecuali, mereka juga objek (dengan atribut). Pelbagai nama yang berbeza dapat diikat pada objek fungsi yang sama.

Inilah contohnya.

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

Pengeluaran

 Hello Hello

Semasa anda menjalankan kod, kedua-duanya berfungsi firstdan secondmemberikan output yang sama. Di sini, nama firstdan secondmerujuk kepada objek fungsi yang sama.

Sekarang keadaan mulai semakin pelik.

Fungsi boleh diteruskan sebagai argumen ke fungsi lain.

Sekiranya anda telah menggunakan fungsi seperti map, filterdan reducedi Python, maka anda sudah mengetahui mengenai perkara ini.

Fungsi sedemikian yang mengambil fungsi lain sebagai argumen juga disebut fungsi urutan lebih tinggi . Berikut adalah contoh fungsi sedemikian.

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

Kami menggunakan fungsi seperti berikut.

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

Selanjutnya, fungsi dapat mengembalikan fungsi lain.

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

Pengeluaran

 Helo

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

Akhirnya, kita mesti mengetahui mengenai Penutupan di Python.

Kembali ke Penghias

Fungsi dan kaedah dipanggil dipanggil kerana mereka boleh dipanggil.

Sebenarnya, sebarang objek yang menggunakan __call__()kaedah khas disebut dipanggil. Jadi, dalam pengertian yang paling asas, penghias adalah panggilan yang mengembalikan panggilan.

Pada dasarnya, penghias menggunakan fungsi, menambah beberapa fungsi dan mengembalikannya.

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

Apabila anda menjalankan kod berikut dalam shell,

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

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

 pretty = make_pretty(ordinary)

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

Kita dapat melihat bahawa fungsi penghias menambahkan beberapa fungsi baru pada fungsi asal. Ini sama dengan mengemas hadiah. Penghias bertindak sebagai pembungkus. Sifat objek yang dihiasi (hadiah sebenarnya di dalam) tidak berubah. Tetapi sekarang, ia kelihatan cantik (sejak dihiasi).

Secara umum, kami menghiasi fungsi dan menetapkannya semula sebagai,

 ordinary = make_pretty(ordinary).

Ini adalah konstruk biasa dan untuk alasan ini, Python mempunyai sintaks untuk mempermudah ini.

Kita boleh menggunakan @simbol bersama dengan nama fungsi penghias dan meletakkannya di atas definisi fungsi yang akan dihiasi. Sebagai contoh,

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

adalah bersamaan dengan

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

Ini hanya gula sintaksis untuk melaksanakan penghias.

Fungsi Menghias dengan Parameter

Penghias di atas adalah ringkas dan hanya berfungsi dengan fungsi yang tidak mempunyai parameter. Bagaimana jika kita mempunyai fungsi yang mengambil parameter seperti:

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

Fungsi ini mempunyai dua parameter, a dan b. Kami tahu ia akan memberikan kesalahan jika kami lulus b sebagai 0.

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

Sekarang mari buat penghias untuk memeriksa kes ini yang akan menyebabkan kesilapan.

 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)

Pelaksanaan baru ini akan kembali Nonesekiranya keadaan ralat timbul.

 >>> 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 menghias fungsi yang mengambil parameter.

Seorang pemerhati yang berminat akan melihat bahawa parameter inner()fungsi bersarang di dalam penghias adalah sama dengan parameter fungsi yang dihiasnya. Dengan mengambil kira ini, sekarang kita dapat membuat penghias umum yang sesuai dengan sebilangan parameter.

In Python, this magic is done as function(*args, **kwargs). In this way, args will be the tuple of positional arguments and kwargs will be the dictionary of keyword arguments. An example of such a decorator will be:

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

Chaining Decorators in Python

Multiple decorators can be chained in Python.

This is to say, a function can be decorated multiple times with different (or same) decorators. We simply place the decorators above the desired function.

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

Output

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

The above syntax of,

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

is equivalent to

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

The order in which we chain decorators matter. If we had reversed the order as,

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

The output would be:

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

Artikel menarik...