#python #generator
#python #генератор
Вопрос:
Я пробовал генераторы python (вместе с from), но в итоге получился бесконечный цикл. Моя версия python — python3. почему я застрял в бесконечном цикле?
Ниже приведен мой код:
def fib2():
a,b = 0,1
while True:
yield a
a,b = b , a b
def FibNumber(num):
fi2= fib2()
for i in range(num):
yield from fi2
if (__name__ == "__main__"):
fin = FibNumber(10)
for i in fin:
print (i)
Ответ №1:
fin
действительно является бесконечным генератором. FiBNumber
не делает того, что вы намеревались; для каждого значения i
он пытается получить все из fi2
. Более правильным определением было бы
def FibNumber(num):
fi2 = fib2()
for i in range(num):
yield next(fi2)
Однако на самом деле вы просто переопределяете itertools.islice
:
from itertools import islice
for i in islice(fib2(), 10):
print(i)
Комментарии:
1. Спасибо за ваш ответ. У меня есть еще одно сомнение в том, что, когда я запускал этот же код в отладчике pdb, я заметил, что он перебирает i в методе FibNumber и печатает числа Фибоначчи одно за другим. То есть вы имеете в виду, что когда я сгенерировал fi2, python3 произвел как можно больше больших итераций и вернул итератор?
Ответ №2:
Это связано с тем, что вы использовали yield from
с бесконечным генератором. В PEP 380 говорится, что:
yield from <expr>
где <expr>
— выражение, вычисляющее итерацию, из которого извлекается итератор. Итератор запускается до исчерпания, в течение которого он выдает и получает значения непосредственно вызывающему или от вызывающего генератора, содержащего выражение yield from («делегирующий генератор»).).
(выделено мной жирным шрифтом)
Комментарии:
1. Добавьте рабочий пример, чтобы ответ был полным
Ответ №3:
Вы можете использовать __next__() во втором итераторе.
def FibNumber(num):
fi2= fib2()
for i in range(num):
yield fi2.__next__()
Ответ №4:
Просто FibNumber(num)
замените на следующее:
def FibNumber(num):
fi2= fib2()
yield from (next(fi2) for i in range(num))
Ответ №5:
Я думаю, вам нужно принудительно прервать цикл for.
def fib2():
a,b = 0,1
while True:
yield a
a,b = b , a b
def FibNumber(num):
fi2= fib2()
a = 0
for i in fi2:
a = 1
if a > num:
break
yield i
if (__name__ == "__main__"):
fin = FibNumber(10)
for i in fin:
print (i)
Ответ №6:
Используйте следующее значение вашего генератора fib2 для каждой последовательности циклов.
def fib2(n):
a,b = 0,1
i = 0
while i <=n:
yield a
a,b = b , a b
def FibNumber(num):
fi2= fib2()
for i in range(num):
yield next(fi2)
if (__name__ == "__main__"):
fin = FibNumber(10)
for i in fin:
print (i)