Bu eğitimde, Python kapatmayı, bir kapatmayı nasıl tanımlayacağınızı ve onu kullanmanız gereken nedenleri öğreneceksiniz.
İç içe geçmiş bir işlevde yerel olmayan değişken
Kapanışın ne olduğuna girmeden önce, iç içe geçmiş bir fonksiyonun ve yerel olmayan değişkenin ne olduğunu anlamalıyız.
Başka bir işlevin içinde tanımlanan bir işleve yuvalanmış işlev denir. İç içe geçmiş işlevler, çevreleyen kapsamın değişkenlerine erişebilir.
Python'da, bu yerel olmayan değişkenler varsayılan olarak salt okunurdur ve onları değiştirmek için onları açıkça yerel olmayan (yerel olmayan anahtar kelime kullanarak) olarak beyan etmeliyiz.
Aşağıda yerel olmayan bir değişkene erişen iç içe geçmiş bir işleve bir örnek verilmiştir.
def print_msg(msg): # This is the outer enclosing function def printer(): # This is the nested function print(msg) printer() # We execute the function # Output: Hello print_msg("Hello")
Çıktı
Merhaba
İç içe geçmiş printer()
işlevin, çevreleyen işlevin yerel olmayan msg değişkenine erişebildiğini görebiliriz.
Kapanış Fonksiyonu Tanımlama
Fonksiyonunun son satırı Yukarıdaki örnekte, ne olur print_msg()
geri printer()
çağırmak yerine fonksiyonunu? Bu, işlevin aşağıdaki gibi tanımlandığı anlamına gelir:
def print_msg(msg): # This is the outer enclosing function def printer(): # This is the nested function print(msg) return printer # returns the nested function # Now let's try calling this function. # Output: Hello another = print_msg("Hello") another()
Çıktı
Merhaba
Bu alışılmadık.
print_msg()
Fonksiyon dizesiyle çağrıldı "Hello"
ve döndürülen işlev adını diğerine bağlandı. Arama sırasında another()
, print_msg()
işlevi gerçekleştirmeyi zaten bitirmiş olmamıza rağmen mesaj hala hatırlanıyordu .
Bazı verilerin ( "Hello
bu durumda) koda eklendiği bu tekniğe Python'da kapatma denir .
Çevreleyen kapsamdaki bu değer, değişken kapsam dışına çıktığında veya işlevin kendisi mevcut ad alanından kaldırıldığında bile hatırlanır.
Çıktıyı görmek için Python kabuğunda aşağıdakileri çalıştırmayı deneyin.
>>> del print_msg >>> another() Hello >>> print_msg("Hello") Traceback (most recent call last):… NameError: name 'print_msg' is not defined
Burada, döndürülen işlev, orijinal işlev silindiğinde bile çalışmaya devam eder.
Ne zaman kapanışlarımız var?
Yukarıdaki örnekten de görüldüğü gibi, iç içe geçmiş bir işlev kendi kapsamı içinde bir değere başvurduğunda Python'da bir kapanışa sahibiz.
Python'da kapanış oluşturmak için karşılanması gereken kriterler aşağıdaki noktalarda özetlenmiştir.
- İç içe geçmiş bir işleve sahip olmalıyız (işlev içinde işlev).
- İç içe geçmiş işlev, çevreleyen işlevde tanımlanan bir değere başvurmalıdır.
- Çevreleyen işlev, yuvalanmış işlevi döndürmelidir.
Kapaklar ne zaman kullanılır?
Peki kapanışlar ne için iyidir?
Kapanışlar, genel değerlerin kullanılmasını önleyebilir ve bir tür veri gizleme sağlar. Ayrıca soruna nesneye yönelik bir çözüm sağlayabilir.
Bir sınıfta uygulanacak birkaç yöntem (çoğu durumda bir yöntem) olduğunda, kapatmalar alternatif ve daha zarif bir çözüm sağlayabilir. Ancak özniteliklerin ve yöntemlerin sayısı arttığında, bir sınıf uygulamak daha iyidir.
Burada, bir sınıfın tanımlanmasından ve nesnelerin yapılmasından daha çok kapanmanın tercih edilebileceği basit bir örnek var. Ama tercih tamamen senin.
def make_multiplier_of(n): def multiplier(x): return x * n return multiplier # Multiplier of 3 times3 = make_multiplier_of(3) # Multiplier of 5 times5 = make_multiplier_of(5) # Output: 27 print(times3(9)) # Output: 15 print(times5(3)) # Output: 30 print(times5(times3(2)))
Çıktı
27 15 30
Python Dekoratörleri de kapsamlı bir kapanış kullanır.
Bir sonuç notunda, kapatma fonksiyonunun içine alınan değerlerin bulunabileceğine işaret etmek iyidir.
Tüm işlev nesneleri __closure__
, bir kapatma işleviyse, hücre nesnelerinin bir demetini döndüren bir niteliğe sahiptir. Yukarıdaki örneğe bakarsak , kapatma fonksiyonlarını biliyoruz times3
ve times5
bunlar.
>>> make_multiplier_of.__closure__ >>> times3.__closure__ (,)
Hücre nesnesi, kapalı değeri depolayan cell_contents niteliğine sahiptir.
>>> times3.__closure__(0).cell_contents 3 >>> times5.__closure__(0).cell_contents 5