ProgramlamaPython geliştirici

Python'da jeneratörler nedir? Nasıl çalışırlar, ne için kullanılırlar ve liste ifadelerinden neyle ayrılırlar?

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

Cevap.

Jeneratörler, Python'da bellek tüketimini baştan sona kaplamadan "anında" diziler oluşturmak için kullanılan özel yinelemeli nesnelerdir. yield anahtar kelimesi ile tanımlanan fonksiyonlar veya jeneratör ifadeleri ((expr for ... in ...)) ile uygulanırlar. Bu, büyük veri setleri veya potansiyel olarak sonsuz akışlarla çalışırken kullanışlıdır.

Liste ifadelerinden temel farklar:

  • Liste ifadeleri ([x for x in range(10)]) bellekte tüm listeyi anında oluşturur.
  • Jeneratörler ((x for x in range(10))) öğeleri birer birer oluşturur ve çok daha az bellek tüketir.

Jeneratörlerin ne zaman kullanılması gerekir:

  • Eğer indeksle erişim gerekmiyorsa.
  • Eğer veriler bellekte saklamak için çok büyükse.
  • Veri akışı işleme düzenlenirken (örneğin dosyadan satır okuma).
# Jeneratör fonksiyonu def counter(n): for i in range(n): yield i for number in counter(5): print(number)

Sıkıntılı bir soru.

"yield ile fonksiyon kullanmak ve normal liste döndüren bir fonksiyon arasındaki fark nedir? Örnek verin."

Cevap: Normal bir fonksiyon, tüm öğeler için bellek alarak anında bir liste hesaplayıp döner. yield ile bir fonksiyon, her defasında bir jeneratör döndürerek öğeleri birer birer sağlayarak tüm diziyi bellek yüklemeden sunar.

def make_list(n): return [i for i in range(n)] # Hemen liste döner, çok fazla bellek kaplar def make_generator(n): for i in range(n): yield i # Tek tek öğe döndürür

Bilgi eksikliği nedeniyle gerçek hata örnekleri.


Hikaye

Büyük günlüğü analiz etmek için hata içeren satırları çıkarmak amacıyla liste ifadeleri kullanıldı:

error_lines = [line for line in open('biglog.txt') if 'ERROR' in line]

Dosya 2 GB'yi aşıyordu ve uygulama OOM (Out of Memory) hatasıyla kapanıyordu. Jeneratör kullanılmalıydı:

error_lines = (line for line in open('biglog.txt') if 'ERROR' in line)

Hikaye

Bir çalışan kısa bir listeyi analiz etmek istedi, yield ile fonksiyon yazdı ama geri dönenin bir jeneratör olduğunu unutmuştu:

result = my_generator_function() # result — jeneratör, liste değil if len(result) > 5: # TypeError: object of type 'generator' has no len()

Düzeltme: sonucu list() içinde sarmak.


Hikaye

Jeneratör üzerinde birkaç kez yineleme yapmaya çalıştılar:

numbers = (i for i in range(5)) for n in numbers: pass # jeneratör tüketildi for n in numbers: print(n) # hiçbir şey yazmaz

Jeneratör tek kullanımlıktır. Yeniden kullanılmak için yeni bir tane oluşturulması gerekir.