Генератором в python называется такая конструкция, возвращающая заместо коллекции итератор по этой коллекции.
def usual_function():
"""
обычная функция, возвращающая список
"""
return [2 * i for i in range(10)]
print "Usual function: {0}".format(usual_function())
Usual function: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
def usual_generator():
"""
обычный генератор
"""
for i in range(10):
yield 2 * i
g = usual_generator()
print "Usual generator: {0}".format(g)
print "Iterating usual generator:"
for j in g:
print j,
print
Usual generator:
Iterating usual generator:
0 2 4 6 8 10 12 14 16 18
Так же генераторы могут возвращать итераторы по бесконечным последовательностям
def endless_prime_generator():
"""
бесконечный генератор простых чисел (построенный на решете Эратосфена)
"""
used_primes = []
current_n = 2
while True:
is_prime = True
for p in used_primes:
if current_n % p == 0:
is_prime = False
break
if is_prime:
used_primes.append(current_n)
yield current_n
current_n += 1
primes = endless_prime_generator()
print "Iterating endless prime generator"
for i in range(10):
print primes.next(),
print
Iterating endless prime generator
2 3 5 7 11 13 17 19 23 29
Но совсем недавно я наткнулся на PEP-342, который вводит в генераторы новшество: теперь yield это не statement, а expression, то есть он может быть использован для присвоения значения какой-то переменной. Чтобы передать в генератор это значение используется метод send.
Простейший пример:
def coroutine():
data = "No data"
while True:
data = "data is {0}".format((yield data))
print "in generator: {0}".format(data)
g = coroutine()
print "First next(): {0}".format(g.next())
print "Then (yield) = None, because next() = send(None)"
for i in range(5):
print g.next()
print "We send Hello: this causes skipping one iteration. {0}".format(g.send("Hello"))
print "And one more example: {0}".format(g.send("Goodbye"))
First next(): No data
Then (yield) = None, because next() = send(None)
in generator: data is None
data is None
in generator: data is None
data is None
in generator: data is None
data is None
in generator: data is None
data is None
in generator: data is None
data is None
in generator: data is Hello
We send Hello: this causes skipping one iteration. data is Hello
in generator: data is Goodbye
And one more example: data is Goodbye
Первой выдачей генератора управлять нельзя. Поэтому первым возвращенным значением будет «No data». То есть выполнится конструкция (yield data). При следующем вызове next() (yield data) вернет None, (next() = send(None)). data станет равна data is None. При вызове send(«Hello») генератор «просыпается», yield data возвращает «Hello», data = «data is Hello», и в таком значении она и возвращается.