Мы посмотрели как сделать простую функцию и использовать колбек, чтобы сделать функцию более универсальной. Мы так же посмотрели как создать итератор для упрощения кода. В этот раз мы собираемся посмотреть как конвертация функции в генератор (после изучения, как это работает) становится наиболее очевидным решением.
Простая функция
В качестве напоминания давайте посмотрим исходную функцию Fibonacci, с которой мы начали, когда мы должны были жестко описать условие, или в более гибком случае использовать колбек.
examples/python/fibonacci_function.py
#!/usr/bin/env python
from __future__ import print_function
def fibonacci():
values = []
while(True):
if len(values) < 2:
values.append(1)
else:
values = [values[-1], values[-1] + values[-2]]
if __name__ == '__main__':
fibonacci()
Генератор
examples/python/fibonacci_generator.py
#!/usr/bin/env python
from __future__ import print_function
def fibonacci():
values = []
while(True):
if len(values) < 2:
values.append(1)
else:
values = (values[-1], values[-1] + values[-2])
yield values[-1]
for f in fibonacci():
if f % 17 == 0:
print(f)
break
if f > 10000:
break
Этот пример с генератором почти такой же, как и простая функция, и мы можем его использовать точно также, как использовали итератор.
Единственное добавление в реализации функции fibonacci
это вызов yield
каждый раз, когда вычислено новое значение.
Этот вызов приостанавливает выполнение функции fibonacci
и возвращает управление вызывающей сущности вместе со значением, переданным в оператор yield
.
В первой итерации цикла for
функция fibonacci
начнет работу
со своего первого оператора создания пустого массива значений values
.
Когда она встретит оператор yield
, она вернет значение values[-1]
, которое
будет присвоено переменной f
в цикле for
, дальше цикл for
продолжит выполнение.
Здесь мы описываем наше условие по прерыванию цикла.
Если мы не прервем выполнение на первой итерации, тогда в последующих итерациях
цикла for
функция fibonacci
продолжит выполнение точно с того места,
где она была приостановлена. Имеется в виду, что содержимое values
будет таким же, каким мы его и оставили, а первый оператор, который будет выполнен после вызова yield
,
это проверка на True
в операторе while(True):
.
Таким образом функция fibonacci
ведет себя точно также, как и итератор Fibonacci,
делая наш код проще.