Soruyu @aib’e sormuşsunuz ama izninizle sorunuza cevap vereyim. Yazdıklarımda bir eksiklik veya bir yanlışlık varsa düzeltilir.
yield
ile return
arasındaki farkı şöyle anlatmaya çalışayım:
a = [i for i in range(1000000)]
Bu yukarıdaki ifade enter tuşuna basılır basılmaz hafızada yer kaplamaya başlayacak. İsterseniz, sistem tepsisini açın ve bu ifadeyi yazıp enter tuşuna basmadan önceki cpu ve hafıza kullanım oranıyla, enter tuşuna bastıktan sonraki cpu ve hafıza kullanım oranını karşılaştırın.
İfadeyi şöyle değiştirelim:
a = (i for i in range(1000000))
Bir de bu ifadeyi yazıp enter tuşuna basın ve hafıza kullanım oranına bir daha bakın.
Yukarıdaki kodlardan ilki, ikincisinden daha fazla kaynak tüketecektir. Aynı durum return
ve yield
deyimleri için de geçerli. Mesela:
def f():
return [i for i in range(1000000)]
yukarıdaki paylaştığım ilk kodlara benzer.
def g():
yield from range(1000000)
Bu ifade ise yukarıda paylaşılan ikinci kodlara benzer.
return
ifadesini şu şekilde kullansaydık, yield
deyimi içeren fonksiyon ile aynı oranda kaynak kullanacaktı.
def f():
return (i for i in range(1000000))
Bu fonksiyon ile yukarıda yield
deyim kullanılan fonksiyon arasında hiç bir fark yok.
# fonksiyonu çağıralım.
call = f()
# Burada bir generator `call` isimli bir değişkene kaydedildi.
print(next(call))
# Bu yukarıdaki kod bize üreteçin ilk değerini verecektir.
print(next(call))
# Bu yukarıdaki kod ise üreteçin ikinici değerini verecektir.
# next() fonksiyonunu üretecin içindeki eleman sayısı kadar kullanabiliriz.
Aşağıdaki örneği bir çalıştırın isterseniz:
def f():
yield from range(5)
yield from "hello"
yield 2
a = f()
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
Bu f()
fonksiyonundaki yield
deyimi, range(5)
deki her bir elemanı, "hello"
stringindeki her bir elemanı ve 2
sayısını bir üreteç içine dahil eder. Dolayısıyla yield
yinelenebilir bir veri setindeki i
verisini sırası geldiğinde kullanır. return
ifadesinde ise veri setinin tamamı kullanılır ve bu da hafızanın daha çok kullanılması anlamına geliyor.
Yinelenebilir verinin büyük olduğu durumlarda yield
deyimini kullanmak return
deyimini kullanmaya göre daha avantajlıdır. Ancak yukarıdaki örneklerden birinde şöyle bir ifade vardı:
def f():
return (i for i in range(1000000))
return
deyimini yukarıdaki gibi kullanırsanız, return
ifadesini yield
gibi kullanmış olursunuz. Yani return
edilen şey bir üreteçtir. Ve bu üreteç ne kadar büyük bir sayı dizisini içeriyor olursa olsun, sayı dizisi hafızada yer tutmaz.