Dekoratörler, İleri Seviye Python Konuların’da fonksiyonların veya metotların davranışını genişletmek veya değiştirmek için kullanılan yüksek seviyeli fonksiyonlardır. Bir dekoratör, bir fonksiyonu veya sınıfı sarmalar ve onun üzerinde ek işlemler yaparak yeni bir fonksiyon veya sınıf döner. Dekoratörler, kodun tekrarını azaltmak ve işlevlerin işleyişini esnek bir şekilde değiştirmek için çok kullanışlıdır.
1. Temel Dekoratörler
Temel bir dekoratör, bir fonksiyonu alır, onun üzerinde işlemler yapar ve ardından değiştirilmiş bir fonksiyon döner. Bu, fonksiyonun işlevselliğini genişletmek veya belirli bir koşula göre davranışını değiştirmek için kullanılabilir.
a. Basit Bir Dekoratör Örneği
Örnek:
def dekorator(func):
def wrapper():
print("Fonksiyon çağrılmadan önce")
func()
print("Fonksiyon çağrıldıktan sonra")
return wrapper
@dekorator
def ornek_fonksiyon():
print("Bu, orijinal fonksiyonun içeriğidir.")
ornek_fonksiyon()
Bu örnekte:
dekorator
adlı dekoratör,ornek_fonksiyon
fonksiyonunu sarmalar ve onun çalışmasından önce ve sonra ek kod çalıştırır.@dekorator
ifadesi,ornek_fonksiyon
fonksiyonuna dekoratörü uygular.
Çıktı:
Fonksiyon çağrılmadan önce
Bu, orijinal fonksiyonun içeriğidir.
Fonksiyon çağrıldıktan sonra
b. Parametre Alan Fonksiyonlar İçin Dekoratörler
Dekoratörler, parametre alan fonksiyonlar için de kullanılabilir. Bu durumda, wrapper
fonksiyonu *args
ve **kwargs
parametreleriyle tanımlanır.
Örnek:
def zamanlayici(func):
import time
def wrapper(*args, **kwargs):
baslangic = time.time()
sonuc = func(*args, **kwargs)
bitis = time.time()
print(f"{func.__name__} fonksiyonu {bitis - baslangic:.4f} saniye sürdü.")
return sonuc
return wrapper
@zamanlayici
def bekle(sure):
time.sleep(sure)
print(f"{sure} saniye bekleme tamamlandı.")
bekle(2)
Bu örnekte:
zamanlayici
dekoratörü, fonksiyonun çalışma süresini ölçer.bekle
fonksiyonu, çalıştırıldığında dekoratör tarafından sarılır ve çalışma süresi hesaplanır.
Çıktı:
2 saniye bekleme tamamlandı.
bekle fonksiyonu 2.0021 saniye sürdü.
2. Dekoratör Fonksiyonlarını Katmanlama (Chaining Decorators)
Bir fonksiyon üzerine birden fazla dekoratör uygulanabilir. Bu durumda, dekoratörler sırasıyla uygulanır.
Örnek:
def dekorator1(func):
def wrapper():
print("Dekoratör 1 çalışıyor")
func()
return wrapper
def dekorator2(func):
def wrapper():
print("Dekoratör 2 çalışıyor")
func()
return wrapper
@dekorator1
@dekorator2
def ornek_fonksiyon():
print("Orijinal fonksiyon çalışıyor")
ornek_fonksiyon()
Bu örnekte, ornek_fonksiyon
önce dekorator2
, ardından dekorator1
ile süslenir.
Çıktı:
Dekoratör 1 çalışıyor
Dekoratör 2 çalışıyor
Orijinal fonksiyon çalışıyor
3. Parametre Alan Dekoratörler
Dekoratörlerin kendileri de parametre alabilir. Bu durumda, dekoratör fonksiyonu, bir dekoratör dönen bir fonksiyon olur.
Örnek:
def tekrarla(n):
def dekorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
func(*args, **kwargs)
return wrapper
return dekorator
@tekrarla(3)
def merhaba():
print("Merhaba!")
merhaba()
Bu örnekte:
tekrarla
dekoratörü, bir fonksiyonunn
kez çalıştırılmasını sağlar.merhaba
fonksiyonu, dekoratör sayesinde üç kez çalıştırılır.
Çıktı:
Merhaba!
Merhaba!
Merhaba!
4. Sınıf Dekoratörleri
Dekoratörler yalnızca fonksiyonlar için değil, sınıflar için de kullanılabilir. Bir sınıf dekoratörü, bir sınıfı sarmalar ve onun davranışını değiştirebilir.
Örnek:
def tekrarla(n):
def dekorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
func(*args, **kwargs)
return wrapper
return dekorator
@tekrarla(3)
def merhaba():
print("Merhaba!")
merhaba()
Bu örnekte:
singleton
dekoratörü,VeriTabani
sınıfının sadece bir kez oluşturulmasını sağlar. İkinci kez aynı sınıftan nesne oluşturulmak istendiğinde, ilk nesne döndürülür.
5. İç İçe Dekoratörler (Nested Decorators)
Dekoratörler iç içe kullanılabilir, yani bir dekoratör başka bir dekoratörün içinde tanımlanabilir.
Örnek:
def log_decorator(level):
def decorator(func):
def wrapper(*args, **kwargs):
print(f"[{level}] {func.__name__} çalıştırılıyor.")
return func(*args, **kwargs)
return wrapper
return decorator
@log_decorator("INFO")
def toplama(a, b):
return a + b
sonuc = toplama(5, 7)
print("Sonuç:", sonuc)
Bu örnekte:
log_decorator
fonksiyonu, bir seviyeye göre (INFO
,ERROR
vb.) fonksiyon çağrılarını loglar.toplama
fonksiyonu çalıştırıldığında, dekoratör sayesinde log mesajı yazılır.
Çıktı:
[INFO] toplama çalıştırılıyor.
Sonuç: 12
6. functools.wraps
ile Dekoratör Fonksiyonlarını Korumak
Dekoratörler, sarmaladıkları fonksiyonun bazı özelliklerini (örneğin, adını ve dokümantasyonunu) kaybedebilir. functools.wraps
dekoratörü, bu özellikleri korumak için kullanılır.
Örnek:
import functools
def dekorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print(f"{func.__name__} fonksiyonu çalıştırılıyor.")
return func(*args, **kwargs)
return wrapper
@dekorator
def ornek_fonksiyon():
"""Bu bir örnek fonksiyondur."""
print("Fonksiyon çalıştı.")
ornek_fonksiyon()
print(ornek_fonksiyon.__name__) # ornek_fonksiyon
print(ornek_fonksiyon.__doc__) # Bu bir örnek fonksiyondur.
Bu örnekte, functools.wraps
, wrapper
fonksiyonunun ornek_fonksiyon
‘un özelliklerini (isim, dokümantasyon vb.) korumasını sağlar.
Dekoratörler, Python’da fonksiyonların ve sınıfların davranışını genişletmek veya değiştirmek için kullanılan güçlü bir araçtır. Kodun tekrarını azaltır, fonksiyonları daha esnek hale getirir ve genel yapıyı daha modüler yapar. Dekoratörler, parametre alabilir, birden fazla dekoratör katmanlanabilir ve sınıflara uygulanabilir. İleri seviye Python projelerinde dekoratörler, fonksiyonel programlamanın önemli bir parçası olarak sıkça kullanılır.
Bir yanıt yazın