ProgramlamaPython Geliştirici

Python'da closure'lar (kapamalar) nasıl çalışır? Dış fonksiyona erişim özellikleri nelerdir ve değiştirilebilir değişkenlerle ilgili tuzaklardan nasıl kaçınılır?

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

Cevap.

Closure'lar (kapamalar) Python'un güçlü bir mekanizmasıdır, çevre bağlamından 'hatırlanmış' verilere sahip fonksiyonlar yaratmaya olanak tanır.

Konunun Tarihi

Fonksiyonel dillerde ve Python'da fonksiyonlar birinci sınıf nesnelerdir. Bir fonksiyon, kendi çevresindeki (dış) görünüm bağlamındaki değişkenleri 'kapatan' yeni bir fonksiyon döndürebilir.

Problem

Geliştiriciler sıkça kapatılan değişkenlerin closure içinde nasıl 'yaşadığını', nasıl okunup yazıldığını, nasıl güvenli bir şekilde çalışılacağını (özellikle değiştirilebilir nesnelerle) karıştırır.

Çözüm

İç fonksiyon dış fonksiyondaki değişkenleri kullanırsa, bu değişkenler otomatik olarak 'hatırlanır' – dış fonksiyon çalışmayı tamamlamış olsa bile. Değişkeni okumak her zaman açıktır, ancak değeri değiştirmek gerektiğinde nonlocal anahtar kelimesini kullanmak gerekir. Değiştirilebilir nesnelerle (listeler, dict'ler) çalışırken bu özellikle riskli bir alandır.

Örnek:

def outer(): count = 0 def inner(): nonlocal count count += 1 return count return inner counter = outer() print(counter()) # 1 print(counter()) # 2

Anahtar özellikler:

  • İç içe fonksiyon, oluşturulduğu anda görünümlerde bulunan değişkenlerin değerlerini hatırlar.
  • Kapatılan değişkenleri değiştirmek için nonlocal kullanın (aksi takdirde işlem yerel bir değişken yaratır).
  • Closure içindeki nesnelere referanslar, dış fonksiyondan çıkılsa bile korunur; bu, fonksiyon fabrikaları, sözdizimsel sayaçlar ve daha fazlasını gerçekleştirmeye olanak tanır.

Tuzak Sorular.

Nonlocal olmadan, bir fonksiyon içinde kapalı bir değişkenin değerini değiştirebilir miyiz?

Hayır. Yeni bir değer atamaya çalıştığınızda nonlocal belirtmeden Python bunu yeni bir yerel değişken oluşturma olarak algılar ve eski değer dışarı çıkmaz.

Örnek:

def make_counter(): count = 0 def inner(): count += 1 # UnboundLocalError! hatası! return count return inner

Closure aracılığıyla dış görünümde argümanlar iletebilir miyiz?

Evet, closure, sınıf nitelikleri, global değişkenler vb. dahil dış görünümdeki herhangi bir değişkeni 'hatırlayacaktır'. Ancak bu değişkenlerin değiştirilmesi, özel çabalar gerektirir (örneğin, nonlocal veya global kullanımı).

Closure içindeki değiştirilebilir nesnelerle ne olur?

Eğer kapalı bir referans, değiştirilebilir bir nesneye (örneğin bir liste) sahipse, içeriğini nonlocal olmadan değiştirebilirsiniz, ama eğer değişkeni yeniden atamaya çalışırsanız – nonlocal gerekecektir.

Örnek:

def make_appender(): result = [] def append(x): result.append(x) # Tamamdır! return result return append f = make_appender() print(f(1)) # [1] print(f(2)) # [1, 2]

Tipik Hatalar ve Anti-Desenler

  • Nonlocal olmadan closure'daki bir değişkeni yeniden atamaya çalışma.
  • Değiştirilebilir durumu saklamak için closure kullanımı; olası bellek sızıntısının farkında olmamak.
  • Çok fazla kapalı değişken nedeniyle okunması zor olan kod.

Gerçek Hayat Örneği

Negatif Durum

Geliştirici bir closure yazar, değişkeni nonlocal olmadan değiştirir – UnboundLocalError oluşur.

Artılar:

  • Hızlı prototipleme sayaçları, fabrikalar için.

Eksiler:

  • Nonlocal hatası olduğunda öngörülemeyen davranış, bug'lar.

Pozitif Durum

Closure'daki yönetilen durum için nonlocal kullanımı.

Artılar:

  • Açıkça kontrol edilen durum, sayaçlar ve fonksiyon fabrikalarını uygulamak kolaydır.

Eksiler:

  • Büyük closure zincirlerini anlamak ve hata ayıklamak daha karmaşık hale gelir.