Python (3.9.1) Generator
- Bu yazıda Python'daki (3.9.1) generator kavramını anlamaya çalışacağız.
- Generator'lar farklı veri tiplerine(integer, float, string, boolean) sahip değerler dizgesi(sequence) üretirler.
- Generator'lar bir veri dizgisi(sequence) ürettiği için iterate edilebilir
- Bir fonksiyonda(methodda)
yieldanahtar kelimesi kullanarak ya da list comprehension yapısı ile generator oluşturulabilir.
xxxxxxxxxx# generator olusturmak icin 1. yontemdef compute(limit): for i in range(limit): yield i# generator olusturmak icin 2. yontemgen = (i for i in range(10))# >>> gen = (i for i in range(10))# >>> type(gen)# <class 'generator'># Asagidaki list comprehension LISTE uretir,# generator DEGIL!# >>> gen2 = [i for i in range(10)]# >>> type(gen2)# <class 'list'>- Generator tüm veriyi hafızada(memory) tutmaz.
- Generator tipindeki bir fonksiyon 1 kere çalışır ve duraklar, iterate edebildiğiniz için fonksiyonu tekrar çağırdığınızda çalışır ve tekrar duraklar.
- Iterasyon bittiği halde çağırmaya çalışırsanız
StopIterationexception alırsınız. - Generator tipinden
listtipine verinizi dönüştürürseniz performans kaybı yaşarsınız. - Iterate edebildiğiniz için generator'daki verilere
next()fonksiyonu ile erişebilirsiniz. - Generator exhausted(tükenmiş) olduktan sonra tekrar üzerinde iterate edemezsiniz.
Örnekler
ornek1.py
xxxxxxxxxxdef compute(limit): for i in range(1, limit+1): yield i*ires = compute(5)Verilere erisim 1. yontem
xxxxxxxxxxprint(next(res)) # 1print(next(res)) # 4print(next(res)) # 9print(next(res)) # 16print(next(res)) # 25# print(next(res)) # StopIteration exceptionxxxxxxxxxx##### Verilere erisim 2. yontemfor r in res: print(r)ornek2.py
xxxxxxxxxxfrom time import sleepdef compute1(limit): result = [] for i in range(limit): sleep(0.5) # yarim saniye bekle result.append(i) return resultprint(compute1(10)) # 5 saniye sonra result gelecekdef compute2(limit): for i in range(limit): sleep(0.5) # yarim saniye bekle yield ifor c2 in compute2(10): print(c2) # yarim saniyede bir degerleri tek tek goster- Çok fazla sayıda verilerle işlem yaptığımızda bütün verilerin işlenmesinin bitmesini beklemek yerine generator yapısını kullanarak zaman ve performans açısından kazançlı çıkabiliyoruz.
ornek3.py
xxxxxxxxxximport timedef compute1(limit): res = [] for i in range(limit): res.append(i) return resdef compute2(limit): for i in range(limit): yield it1s = time.perf_counter()compute1(1_000_000)t1e = time.perf_counter()print(f"compute1 duration: {t1e-t1s}")t2s = time.perf_counter()compute2(1_000_000)t2e = time.perf_counter()print(f"compute2 duration: {t2e-t2s}")- Generator veri yapıları list veri yapılarına göre daha performanslıdır. Yukarıdaki örneği çalıştırınca aşağıdaki sonuçları alıyoruz. Aradaki hız farkını görebilirsiniz.
xxxxxxxxxx└─ λ python ornek3.py compute1 duration: 0.09740092599986383compute2 duration: 7.3659998633957e-06 # yani (7.3659998633957)*(10^-6) = 0.0000073659998633957(env) adnan @ kaya ~/Desktop/py └─ λ python ornek3.py compute1 duration: 0.0913018249993911compute2 duration: 1.4819000170973595e-05(env) adnan @ kaya ~/Desktop/py └─ λ python ornek3.py compute1 duration: 0.0924550449999515compute2 duration: 8.418000106757972e-06(env) adnan @ kaya ~/Desktop/py └─ λ python ornek3.py compute1 duration: 0.09621888899982878compute2 duration: 1.4583999472961295e-05(env) adnan @ kaya ~/Desktop/py └─ λ python ornek3.py compute1 duration: 0.09367401999952563compute2 duration: 8.56200040288968e-06Corey Schafer Kod Örneği Çıktısı
xxxxxxxxxx └─ λ python generator_people.py Memory (Before): 24.76953125Mbpeople_list Memory (After) : 295.453125Mbpeople_list Took 1.5263274680000904 Secondspeople_generator Memory (After) : 25.89453125Mbpeople_generator Took 0.09679912100000365 Seconds- Görüldüğü gibi listeler hafızada daha çok alan kapladığı gibi generator'lere göre daha yavaş çalışmaktadır.
Yorumlar