Panduan Dekorator Python untuk Programmer Tingkat Lanjut

Dekorator Python adalah alat yang kuat dan fleksibel untuk mengubah perilaku fungsi atau metode. Dekorator ini memungkinkan programmer untuk memperluas atau mengubah fungsionalitas objek yang dapat dipanggil dengan cara yang bersih, mudah dibaca, dan mudah dipelihara. Artikel ini membahas konsep lanjutan yang terkait dengan dekorator Python, termasuk dekorator bersarang, argumen dekorator, dan dekorator berbasis kelas.

Apa itu Dekorator?

Dekorator adalah fungsi yang mengubah perilaku fungsi lain. Dekorator membungkus fungsi lain untuk memperluas perilakunya tanpa mengubah kodenya secara eksplisit. Dekorator didefinisikan menggunakan sintaks @decorator_name dan ditempatkan di atas definisi fungsi.

Sintaksis Dekorator Dasar

Dekorator sederhana mengambil suatu fungsi sebagai argumen, mendefinisikan fungsi bagian dalam yang menambahkan beberapa perilaku, lalu mengembalikan fungsi bagian dalam.

def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

Fungsi Dekorator dengan Argumen

Dekorator dapat lebih fleksibel dengan menerima argumen. Untuk membuat dekorator seperti itu, Anda perlu menulis fungsi yang mengembalikan dekorator. Ini memungkinkan penambahan perilaku yang lebih dinamis ke dekorator.

def repeat(num_times):
    def decorator_repeat(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                func(*args, **kwargs)
        return wrapper
    return decorator_repeat

@repeat(num_times=3)
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")

Dekorator Bersarang

Dekorator dapat disusun untuk menggabungkan beberapa perilaku. Misalnya, kita dapat menggunakan dua atau lebih dekorator pada satu fungsi.

def uppercase_decorator(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result.upper()
    return wrapper

def repeat_decorator(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result + result
    return wrapper

@repeat_decorator
@uppercase_decorator
def say_word(word):
    return word

print(say_word("hello"))

Dekorator Berbasis Kelas

Dalam Python, dekorator juga dapat diimplementasikan sebagai kelas dengan menggunakan metode __call__. Dekorator berbasis kelas berguna saat Anda memerlukan manajemen status dan perilaku yang lebih kompleks.

class CountCalls:
    def __init__(self, func):
        self.func = func
        self.num_calls = 0

    def __call__(self, *args, **kwargs):
        self.num_calls += 1
        print(f"Call {self.num_calls} of {self.func.__name__!r}")
        return self.func(*args, **kwargs)

@CountCalls
def say_hello():
    print("Hello!")

say_hello()
say_hello()

Menggunakan functools.wraps untuk Mempertahankan Metadata

Saat Anda menulis dekorator, fungsi yang dihias akan kehilangan metadata aslinya, seperti nama dan docstring-nya. Dekorator functools.wraps dapat digunakan untuk menyalin metadata fungsi asli ke fungsi pembungkus.

from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print("Wrapper function executed before", func.__name__)
        return func(*args, **kwargs)
    return wrapper

@my_decorator
def display_info(name, age):
    """Displays name and age."""
    print(f"display_info ran with arguments ({name}, {age})")

print(display_info.__name__)  # Output: display_info
print(display_info.__doc__)   # Output: Displays name and age.

Kesimpulan

Dekorator Python merupakan fitur hebat yang memungkinkan desain kode dan modifikasi perilaku yang fleksibel. Penggunaan tingkat lanjut, seperti dekorator bertingkat, dekorator dengan argumen, dan dekorator berbasis kelas, dapat menyediakan fungsionalitas dan keterbacaan yang lebih baik pada program Python. Dengan memahami dan memanfaatkan dekorator dengan benar, pengembang dapat menulis kode yang lebih ringkas, efisien, dan mudah dibaca.