Decorators (Süsleyiciler)

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 fonksiyonun n 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.

Comments

“Decorators (Süsleyiciler)” için bir yanıt

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Bu site, istenmeyenleri azaltmak için Akismet kullanıyor. Yorum verilerinizin nasıl işlendiği hakkında daha fazla bilgi edinin.