Sunday, February 27, 2011

Fonksiyon Gezmek ve Yield

Bir vektorun, listenin elemanlarini gezebildigimizi (iteratation) biliyoruz.

Python'un uretici (generators) ozelligi ile bir fonksiyonu gezmek te mumkun.

Bu nasil oluyor? Hokus pokus "yield" adi verilen bir komutta.

Bir fonksiyon return cagrisi ile bir deger döndürebilir. Fakat o noktada o fonksiyondan disari cikmis oluruz yani o fonksiyon ile isimiz biter. Kiyasla yield ile bir deger döndürürüz, geriye bir sonuc gelir ama fonksiyonun yield anindaki hali "dondurulur" -- yani unutulmaz. Fonksiyondan disari cikmis olsak bile geri donebiliriz, ve lokal degiskenleri olduklari halde kullanmaya devam edebiliriz: Alttaki fonksiyona bakalim:
def fib():
a, b = 0, 1
while 1:
yield b
a, b = b, a+b
Bu fonksiyon Fibonacci sayilarini uretir, Fibonacci sayilari 1,1,2,3 diye gider, bir sonraki sayi her zaman onceki iki sayinin toplamidir. Goruldugu gibi yield ile en son toplami döndürüyoruz, fonksiyondan "cikiyoruz", fakat gezme islemi bir sonraki degeri istediginde fib()'e geri donuluyor ve islem yield'den bir sonraki satirdan, yani kaldigi yerden devam ediyor. Fonksiyon icindeki tum lokal degiskenler hala degerlerini koruyorlar.

Kullanmak icin fib() cagrisini sanki bir listeymis gibi cagirabiliriz:
for x in fib(): print x
Yukarida anlatilan turden deger gezme olanaginin faydasi nedir? Kod duzenlemesi acisindan getirdigi faydalar otesinde (temizlik gibi, gecici bir liste objesine gerek yok), performans bakimindan faydasi olabilir. Bir sekilde hesaplanan ve uretilen elemanlari gezmek icin onlarin onceden bir listeye doldurulmus olmasi gerekmiyor -- her eleman fonksiyon tarafindan "gerektigi anda" hesaplanip teker teker aliniyor, ve bu bir tur "tembel (lazy)" hesaplama olarak gorulebilir. CPU bedelini her Fibonacci sayisini uretirken sadece o sayi icin oduyoruz. 10 tane onceden uretip bir yerde bekletmiyoruz.

Kaynak

No comments: