"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.
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.
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.
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
nonlocal anahtar kelimesi kullanılır.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
nonlocal olmadan, closure'un otomatik olarak dış değişkeni değiştirdiğini beklemek.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ı:
Eksileri:
i değişkenine referans verir, en son değeri 2 olur — bu yüzden çoğu insan için beklenmedik davranış.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ı:
Eksileri: