Python'da dekoratörler, kodu daha kompakt ve okunabilir hale getirmek için, fonksiyonlar ve metotlar etrafında tekrar eden davranışları kapsülleyerek geliştirilmiş bir yöntemdir. @decorator sentezinin ortaya çıkmasından önce, bunlar açıkça uygulanıyordu ve bu durum kodun anlaşılmasını zorlaştırıyordu. Günümüzde dekoratörler, mantığı düzenlemede, tekrar eden kontrollerde, günlüklendirmede, önbelleklemede ve daha fazlasında anahtar bir rol oynamaktadır.
Dekoratörlerle çalışırken karşılaşılan sorun, fonksiyonlar, örnek metotları ve statik/sınıf metotları arasındaki farklılıkların doğru bir şekilde işlenmesidir. Genellikle, yöntem bilgilerini kaybetme, self'in geç/erken bağlanması ile ilgili hatalar ve fonksiyonun imzasıyla (signature) alakalı sorunlar ortaya çıkmaktadır.
Çözüm, evrensel dekoratörler yazarken functools.wraps modülünü kullanarak meta verileri korumak ve ayrıca süslenen nesnenin türüne dikkat etmektir (örneğin, örnek metotlarının ilk argüman olarak self alacağını doğru bir şekilde göz önünde bulundurmak).
Kod örneği:
import functools def my_decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): print(f"Fonksiyondan önce: {func.__name__}") result = func(*args, **kwargs) print(f"Fonksiyondan sonra: {func.__name__}") return result return wrapper class Example: @my_decorator def method(self, x): print(f"{x} ile metot çağrıldı") ex = Example() ex.method(5)
Önemli noktalar:
functools.wraps kullanılması önerilir.Bir fonksiyon için yazılmış bir dekoratörü, sınıf metodu üzerinde kullanmak zorunlu mudur ve self ile ne olur?
Hayır, dekoratör kendi başına çalışır, ancak wraps kullanılmadığında fonksiyonun adı, IDE yardımı ve belge kaybolur. Self yine de ilk parametre olacaktır, ancak meta veri kaybı hata ayıklamayı ve refleksiyonu zorlaştıracaktır.
def bad_decorator(f): def wrapper(*args, **kwargs): print("dekoratör uygulanmış") return f(*args, **kwargs) return wrapper class Test: @bad_decorator def foo(self): pass print(Test().foo.__name__) # wrapper
Aynı dekoratörü hem örnek metodu hem de statik metot için uygulamak mümkün mü?
Mümkündür, ancak unutmamak gerekir: statik metotlar ilk argüman olarak self almaz. Eğer dekoratör self ile çalışmak üzere tasarlanmışsa, @staticmethod/ @classmethod ile hata ortaya çıkacaktır.
Dekoratör yöntem imzasını ve otomatik tamamlama özelliğini nasıl etkiler?
En basit şekilde: functools.wraps olmadan imza ve dökümantasyon kaybolur, IDE ve birçok yardımcı araç doğru bir şekilde çalışmamaya başlar.
Olumsuz vaka: Tüm sınıf metotlarında functools.wraps kullanılmadan dekoratörler.
Artılar: hızlı prototip, çalışıyor.
Eksiler: hata ayıklama için yığın izlemek imkansız, IDE imzayı önermez.
Olumlu vaka: Dekoratörler functools.wraps kullanıyor, kod belgelenmiş.
Artılar: okunabilirlik, bakım, IDE konforu.
Eksiler: minimum sözdizimi ve dikkat ek yükü.