Бесконечная проблема доходности - PullRequest
5 голосов
/ 01 ноября 2010

Вот мой простой код

class Fibonacci:
    @staticmethod
    def series():
        fprev = 1
        fnext = 1
        yield fnext
        while True:
            yield fnext
            fprev,fnext = fnext,fprev+fnext

under10 = (i for i in Fibonacci.series() if i<10)
for i in under10 :
    print i

Это абсолютно очевидно, но ... ПОЧЕМУ интерпретатор выполняет блок

while True:
                yield fnext
                fprev,fnext = fnext,fprev+fnext

навсегда? Я указал в генераторе, что я хочу только элементы <10 </p>

under10 = (i for i in Fibonacci.series() if i<10)

ИМХО, это немного недоразумение Любой способ предотвратить бесконечное выполнение без переписывания "серии"?

Ответы [ 3 ]

16 голосов
/ 01 ноября 2010

Как переводчик должен знать, что все будущие числа будут <10? Он должен либо <em>знать (каким-то образом), что он производит серию Фибоначчи, либо должен проверять всю серию.

Он не может сделать первое, поэтому он делает второе.

Это можно исправить с помощью itertools.takewhile:

import itertools

under10 = itertools.takewhile(lambda n: n < 10, Fibonacci.series())
0 голосов
/ 01 ноября 2010

Бесконечный цикл не является результатом while True: в методе Fibonacci.series().Это вызвано генератором under10 = (i for i in Fibonacci.series() if i<10), который просто продолжает работать, так как не понимает, что полученные значения никогда не уменьшатся.Вот [другой] способ исправить это и обобщить его одновременно - без переписывания series() - с помощью итератора itertools.takewhile():

import itertools
fibos_under = lambda N: itertools.takewhile(lambda f: f < N, Fibonacci.series())

for i in fibos_under(10):
    print i

Кстати: Вы можете немного упростить метод Fibonacci.series(), изменив его на тот, который дает те же значения:

class Fibonacci:
    @staticmethod
    def series():
        fprev,fnext = 0,1
        while True:
            yield fnext
            fprev,fnext = fnext,fprev+fnext
0 голосов
/ 01 ноября 2010
under10 = (i for i in Fibonacci.series() if i<10) 

Продолжит работать, просто не даст значений больше 10. Нет ничего, что инструктирует цикл for останавливаться.

Возможно, вам повезет больше, если вы сделаете что-то вроде:

for i in Fibonacci.series():
    if i > 10:
        break
    #do your appends and such here

РЕДАКТИРОВАТЬ:

Мне гораздо больше нравится пример itradtools Конрада, я всегда забываю об itertools

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...