Python
Parametreli decorator
Parametreli decorator yazmayı öğrenirsin.
Parametreli decorator
Bir decorator, başka bir fonksiyonu saran ve davranışını değiştiren çağrılabilen bir nesnedir. Parametreli decorator ise, sarma işlemini yapılandıran ek argümanlar alır.
Önce dışta bir factory fonksiyonu tanımlanır: def repeat(n):. Bu fonksiyon, gerçek decorator'ü döndürür; decorator de sarmalanan fonksiyonu döndürür. Üç katmanlı yapı şöyledir:
def repeat(n):
def deco(fn):
def wrapper(*args):
for _ in range(n):
fn(*args)
return wrapper
return deco
Kullanımı @repeat(3) biçimindedir; çağrıdaki 3 argümanı factory'ye gider.
functools.wraps ile imza koruma
Bir decorator, sarmaladığı fonksiyonun adını, docstring'ini ve imzasını kaybeder; çünkü artık wrapper çağrılır. Bu durum hata ayıklamayı ve yardım çıktısını bozar.
Çözüm: functools.wraps(fn) decorator'ünü wrapper'ın üstüne koymak. Orijinal fonksiyonun meta verilerini wrapper'a kopyalar.
from functools import wraps
def repeat(n):
def deco(fn):
@wraps(fn)
def wrapper(*args):
...
return wrapper
return deco
Böylece help(my_fn) hâlâ orijinal docstring'i gösterir.
Uygulama Parametreli @repeat decorator'ü yaz
Üç katmanlı bir parametreli decorator yaz. Factory repeat(n), decorator deco(fn) ve sarmalayan wrapper(*args) iç içe olsun. wrapper, fn(*args) çağrısını tam n kez yapsın. @wraps(fn) ile meta veriyi koru. @repeat(2) ile süslenmiş greet(name) fonksiyonu name değerini iki kez yazdırsın; en son greet("Ayşe") çağrısını yap.
Örnek çözümü göster
from functools import wraps
def repeat(n):
def deco(fn):
@wraps(fn)
def wrapper(*args):
for _ in range(n):
fn(*args)
return wrapper
return deco
@repeat(2)
def greet(name):
print(name)
greet("Ayşe")
Kendini test et
-
Parametreli decorator'de @repeat(3) çağrısındaki 3 nereye gider?
- Factory fonksiyonuna (repeat)
- Doğrudan sarmalanan fonksiyona
- wrapper fonksiyonuna
- deco fonksiyonuna
Cevabı göster
Factory fonksiyonuna (repeat) — repeat(3) önce factory'yi çağırır; 3 factory'nin n parametresine bağlanır.
-
wraps decorator'ünü ekle
from functools import wraps
def repeat(n):
def deco(fn):
@____(fn)
def wrapper(*args):
for _ in range(n):
fn(*args)
return wrapper
return deco
Cevabı göster
from functools import wraps
def repeat(n):
def deco(fn):
@wraps(fn)
def wrapper(*args):
for _ in range(n):
fn(*args)
return wrapper
return deco
-
Parametreli decorator katmanlarını eşleştir
- repeat(n)
- En dış factory
- deco(fn)
- Gerçek decorator
- wrapper(*args)
- Sarmalayan fonksiyon
- @wraps(fn)
- Meta veriyi korur
Sıradaki ders: Class decorator