Пару слов о генераторах в Python


Генератором в 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», и в таком значении она и возвращается.

Реклама

Метки: , , , , , , , ,

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s


%d такие блоггеры, как: