ProgramlamaBackend Geliştirici

Python'da closure'ların (kapama) nasıl çalıştığını, normal fonksiyonlardan neyle farklılık gösterdiğini ve pratik uygulama alanlarını açıklayınız.

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Konunun Tarihçesi

"Closure" terimi, fonksiyonel programlamadan alınmış olup Python'da başından beri mevcuttur. Closure'lar, bir fonksiyonun oluşturulduğu ortamı hatırlamasını sağlar, bu durumda çağrıldığında bu ortam dışında da çalışabilirler. Bu kavram esneklik sağlar ve birçok kalıbı, işlev fabrikaları ve tembel hesaplamalar gibi uygulamaları gerçekleştirmeye olanak tanır.

Sorun

Python'da fonksiyonlar birinci sınıf nesnelerdir. Bazen, iç içe geçmiş bir fonksiyonun, dış fonksiyon tamamlandıktan sonra bile dışarıdaki değişkenleri kullanması gerektiği durumlar ortaya çıkar. Normal bellek alanı dönerken bunu garanti etmez. Eğer böyle bir fonksiyon, oluşturulma ortamındaki değişkenlere referans verirse, bu durumda bir closure meydana gelir.

Çözüm

Closure, iç fonksiyonun dış fonksiyonda tanımlanan değişkenlere referans vermesi ve bu dış fonksiyonun iç fonksiyonu dışarıda döndürmesi durumunda oluşur. Bu sıklıkla işlev fabrikaları yaratmak, sınıflar olmadan durumları kapsüle etmek ve "yerinde" parametrelerle bir fonksiyon oluşturmak için kullanılır.

Kod Örneği:

def make_multiplier(factor): def multiplier(x): return x * factor return multiplier mul2 = make_multiplier(2) mul3 = make_multiplier(3) print(mul2(10)) # 20 print(mul3(10)) # 30

Temel Özellikler:

  • Closure, dış fonksiyon tamamlandığında bile ortam değişkenlerinin değerlerini saklar.
  • İç fonksiyondaki durum esasen özel, dışarıdan doğrudan değiştirilemez.
  • Dıştaki değişkeni closure içerisinde değiştirmek için nonlocal anahtar kelimesi kullanılır.

Zorlu Sorular.

Closure, iç fonksiyon içinde değişken değişirse, çağrılar arasında değiştirilebilir durumu saklayabilir mi?

Evet, iç fonksiyonda nonlocal anahtar kelimesi kullanılırsa. nonlocal olmadan atama, dışarıyı değiştirmeden yeni bir yerel değişken yaratır.

def counter(): count = 0 def inc(): nonlocal count count += 1 return count return inc c = counter() print(c()) # 1 print(c()) # 2

Python'da sınıflar yerine closure kullanarak özel değişkenler uygulanabilir mi?

Evet, closure, iç fonksiyonda getter/setter'lar sağlanmadıkça dışarıdan erişilemeyen "özel" değişkenlerin basit bir uygulamasını sunar.

Closure sadece fonksiyonlar için mi uygulanır? Python'da closure ile lambda fonksiyonları oluşturulabilir mi?

Evet, closure, lexikal değişkenlerin bağlanması açısından def'e benzer olduğu için lambda ifadeleriyle de oluşabilir.

def make_power(n): return lambda x: x ** n square = make_power(2) cube = make_power(3) print(square(4)) # 16 print(cube(2)) # 8

Yaygın Hatalar ve Anti-Desenler

  • nonlocal olmadan, closure'un otomatik olarak dış değişkeni değiştirdiğini beklemek.
  • Closure'da değiştirilebilir nesneleri yakalamak ve bunları değiştirmek, hata ayıklama sırasında zorluklarla karşılaşmadan işlemek.
  • Doğru değişken bağlama olmadan bir döngüde fonksiyon yaratmak (tüm fonksiyonların değişkenin son değerini görmesi tuzağı).

Gerçek Hayattan Örnek

Olumsuz Durum

Bir döngüde işleyiciler oluşturan bir fonksiyon fabrikası, closing içinde döngü değişkenini kullanıyor:

handlers = [] for i in range(3): def handler(x): return x + i handlers.append(handler) print([h(10) for h in handlers]) # [12, 12, 12]

Artıları:

  • Basit, az kod.

Eksileri:

  • Tüm işleyiciler aynı i değişkenine referans verir, en son değeri 2 olur — bu yüzden çoğu insan için beklenmedik davranış.

Olumlu Durum

Değeri "kilitlemek" için varsayılan bir argüman kullanılır:

handlers = [] for i in range(3): def handler(x, j=i): return x + j handlers.append(handler) print([h(10) for h in handlers]) # [10, 11, 12]

Artıları:

  • Gerekli değeri bağlaması.
  • Öngörülebilir davranış.

Eksileri:

  • Bu ince ayrıntıyı hatırlamak ve closure'u manuel düzeltmek gerekebilir, bu da kodun sürdürülmesini zorlaştırır.