Latihan: Decorator
Latihan: Membuat Authentication Decorator
Pada latihan ini, kita akan membuat sebuah custom decorator yang digunakan untuk memeriksa apakah seorang user memiliki akses untuk menjalankan sebuah function.
Decorator yang dibuat bernama authenticated.
Function hanya boleh dijalankan apabila nilai valid pada data user adalah True.
Tujuan Latihan
Diberikan sebuah data user:
user1 = {
"name": "Sorna",
"valid": True
}
Buatlah decorator @authenticated yang memiliki aturan:
- Jika
user["valid"]bernilaiTrue, function dijalankan. - Jika
user["valid"]bernilaiFalse, function tidak dijalankan. - Jika user tidak valid, tampilkan pesan
"invalid user".
Decorator tersebut akan digunakan pada function:
@authenticated
def message_friends(user):
print("message has been sent")
Kode Awal
Berikut kode latihan yang perlu dilengkapi:
user1 = {
"name": "Sorna",
"valid": True
}
def authenticated(fn):
# Buat decorator di sini
pass
@authenticated
def message_friends(user):
print("message has been sent")
message_friends(user1)
Hasil yang Diharapkan
Jika:
"valid": True
maka:
message has been sent
Jika diubah menjadi:
"valid": False
maka:
invalid user
Petunjuk
Perhatikan bahwa message_friends() menerima sebuah argument berupa dictionary:
message_friends(user1)
Karena decorator harus dapat menerima argument tersebut, gunakan:
*args
**kwargs
pada wrapper.
Kemudian periksa nilai valid dari user.
Secara konsep:
message_friends(user1)
↓
authenticated
↓
wrapper
↓
user valid?
↙ ↘
True False
↓ ↓
function "invalid user"
dijalankan
Solusi
user1 = {
"name": "Sorna",
"valid": True
}
def authenticated(fn):
def wrapper(*args, **kwargs):
if args[0]["valid"]:
return fn(*args, **kwargs)
else:
return print("invalid user")
return wrapper
@authenticated
def message_friends(user):
print("message has been sent")
message_friends(user1)
Penjelasan Solusi
Decorator menerima function melalui parameter:
def authenticated(fn):
Kemudian dibuat wrapper:
def wrapper(*args, **kwargs):
Penggunaan *args dan **kwargs memungkinkan wrapper menerima argument dari function yang didekorasi.
Pada saat:
message_friends(user1)
dictionary user1 masuk ke dalam args.
Karena user1 merupakan argument pertama, kita dapat mengaksesnya melalui:
args[0]
Kemudian nilai valid diperiksa:
if args[0]["valid"]:
Jika bernilai True, function asli dijalankan:
return fn(*args, **kwargs)
Jika bernilai False, function asli tidak dijalankan dan program menampilkan:
print("invalid user")
Menguji User Valid
Dengan:
user1 = {
"name": "Sorna",
"valid": True
}
ketika menjalankan:
message_friends(user1)
hasilnya:
message has been sent
Menguji User Tidak Valid
Ubah nilai valid menjadi:
user1 = {
"name": "Sorna",
"valid": False
}
Kemudian:
message_friends(user1)
hasilnya:
invalid user
Function:
print("message has been sent")
tidak dijalankan karena user tidak memiliki status valid.
Poin Pembelajaran
Latihan ini menggabungkan beberapa konsep decorator yang telah dipelajari:
- Function sebagai First-Class Citizen.
- Higher-Order Function.
- Custom decorator.
- Wrapper function.
*argsdan**kwargs.- Mengakses argument dari wrapper.
- Kondisi untuk menentukan apakah function asli dijalankan.
- Menggunakan decorator untuk authentication atau authorization sederhana.
Pola yang digunakan dapat digambarkan sebagai:
@authenticated
↓
message_friends()
↓
wrapper()
↓
periksa user["valid"]
↓
┌───┴───┐
↓ ↓
True False
↓ ↓
fn() invalid user
Latihan ini menunjukkan salah satu penggunaan nyata decorator, yaitu mencegah sebuah function dijalankan apabila kondisi tertentu tidak terpenuhi.