Цикл в генераторе python

#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)