Dalsi pekny clanek.
Stalo by ale asi za to vysvetlit na prikladu k cemu jsou vlastne generatory dobre. Jejich hlavni vyznam vidim v tom, ze umoznuji do pythonu zavest "lenost" (laziness) znamou z funkcionalniho programovani. Napr.
for i in range(10000):
____if i == 5:
________break
nejprve vytvori list o 10000 polozkach a potom pri iteraci precte jen 6. Oproti tomu:
for i in xrange(10000):
____if i == 5:
________break
pri pouziti xrange, coz je vlastne range prepsany jako generator, se vygeneruje pouze tech 6 hodnot vzdycky az kdyz jsou treba (coz v tomto pripade usetri spoustu pameti i casu).
Lze takhle vytvaret napr. nekonecne generatory, pokud z nich pak pouzijete jen urcitou cast (treba nejaky iterativni vypocet, ktery stale konverguje k presne hodnote a jen na vas je jakou chcete presnost a kolik polozek si z nej vezmete).
def t (): print 'start t'; yield 1
def u (): print 'start u'; t ()
def v (): print 'start v'; return t ()
>>> print t()
<generator object at 0x8155238>
>>> print u()
start u
None
>>> print v()
start v
<generator object at 0x8155238>
Definice generatoru je zcela stejna jako definice funkce. V dobe prekladu NELZE urcit, zdali jako prvni bude provaden RETURN, nebo YIELD. Nechapu proto proc se v prvnim pripade vraci generator DRIV nez se provede ten print. Museji provadet statickou analyzu pri prekladu- coz je SPATNA vec.
Druhe volani ukazuje ze iterator nefunguje transparentne jak by mel, musim na pohled dost nelogicky VRACET navratovou hodnotu iteratoru, prestoze ten zadnou navratovou hodnotu nema (ma jen yieldy, na konci zadny return neni).
Treti priklad ukazuje ze kdyz se ten druhy opravi tak aby fungoval, je chovani iteratoru nekonzistentni s prvnim pripadem.