#python #yield
Пример из изучаемой мною книжки
def fibonacci_generator():
a = b = 1
while True:
yield a
a, b = b, a + b
print(a, b) #поможет лучше понять работу
fib = fibonacci_generator()
for i in fib:
if i > 100:
break
else:
print('Generated:', i)
Что в данном коде выполняет функция yield? В книге написано - "Она [генераторная
инструкция], начинается с ключевого слова yield и определяет объект-генератор (то есть
переменную a?), который возвращается оператору (print?), вызвавшему функцию. Когда
генераторная инструкция исполняется, состояние объекта генератора "замораживается"
и сохраняется. Объект, возвращаемый генераторной инструкцией, может быть присвоен переменной
(это мы сделали на 7 строке кода?)."
Но я так и не понял, как это отражается в результате кода?
Я пытаюсь понять работу кода сопоставив код с результатом его выполнения. Вот несколько
строк результата:
Generated: 1
1 2
Generated: 1
2 3
Generated: 2
3 5
Generated: 3
5 8
Generated: 5
8 13
...
Что после операций a, b = b, a + b становится содержимым функции fibonacci_generator?
Результат суммы a и b? Переменная а на второй итерации равна 2, потому что "при этом
она сохраняет состояние своего последнего вызова и при следующем вызове продолжает
работу с той же точки."? Почему, к примеру, на первой итерации, вывод переменной b
отображает 2, ведь сумма а + b просто какое-то, ничему не присвоенное выражение?
Ответы
Ответ 1
yield определяет объект-генератор (то есть переменную a?) Нет, под объектом генератором подразумевается вся функция целиком. Она преобразуется в генератор, если в её теле присутствует инструкция yield. Переменная a — это то, что будет генерироваться и возвращаться. который возвращается оператору (print?) Нет, генератор в Вашем коде возвращается и присваивается переменной fib: fib = fibonacci_generator() print(type(fib)) #Объект, возвращаемый генераторной инструкцией, может быть присвоен переменной (это мы сделали на 7 строке кода?) Нет, в 7 строке кода Вы возвращаете новое сгенерированное значение и замораживаете генератор, а присваивание этого значения переменной неявно происходит в 9 строке кода: for i in fib: ... Инструкция for на каждой итерации будет присваивать i какое-то значение. Для этого она будет обращаться к функции (через методы итерирования). Вы вручную можете получать новые значения из генератора, используя функцию next: i = next(fib) Попробуйте отказаться от цикла for и использовать только инструкцию выше, чтобы лучше понять, как генератор возвращает новое значение. a, b = b, a + b Это сокращённая запись кортежного присваивания: (a, b) = (b, a + b) Элементы из левого кортежа будут сопоставлены с элементами из правого (количество должно быть одинаково) и им будут присвоены соответствующие значения. Ответ 2
a, b = c, d это почти то же самое, что a = c b = d только вычисляется не последовательно, а справа налево. Чтобы поменять местами два значения можно написать a, b = b, a У тебя почти то же самое, но вместо второй переменной сумма: a, b = b, a + bОтвет 3
Генераторы это очень интересная штука. https://docs.python.org/3/reference/expressions.html#generator-expressions Вот документация. Простым языком: yield - это выражение, которое используется при создании функции-генераторы или асинхронного генератора. Еще проще: генератор - это конструкция, в которой реализован протокол итератора, т.е. любой генератор = итерируемая последовательность, которую можно перебирать в цикле, как списки, только значения она возвращает вызовом метода next(), значит - не сразу, а последовательно, за каждое обращение.
Комментариев нет:
Отправить комментарий