微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

斐波那契生成器迭代器和无限生成器

如何解决斐波那契生成器迭代器和无限生成器

我有这个 FibIter 发生器。我正在尝试使用生成器表达式创建第二个。

def FibIter():
    yield 0
    yield 1
    x = 0
    y = 1
    while True:
        result = x + y
        x,y = y,result
        yield result

fibiter = FibIter()
fibiter_in_range = (x for i,x in enumerate(fibiter) if 100000 < i <= 100020)

现在,如果我在下面运行代码,什么都不会发生。

print(list(fibiter_in_range))

如果我运行下面的代码,数字会被打印出来,但 for 循环不会结束。

for x in fibiter_in_range:
    print(x)

我想我可以遍历 fibiter_in_range 直到使用完所有元素。

我对生成器有什么不了解?如何优雅地创建带有 n 范围为 100000-100020 的斐波那契数的迭代器?

解决方法

问题是您的生成器永远不会结束,即使在 i 达到其上限之后,您的生成器表达式也会不断从中获取输出。

做你想做的一个简单的方法是使用itertools.islice

from itertools import islice

def FibIter():
    yield 0
    yield 1
    x = 0
    y = 1
    while True:
        result = x + y
        x,y = y,result
        yield result

fibiter = FibIter()
fibiter_in_range = islice(fibiter,10,15)
print(list(fibiter_in_range))
# [55,89,144,233,377]
,

Python 不够聪明,无法知道 if 100000 < i <= 100020 会导致新生成器在 100020 后停止生成。据它所知,后面可能会有一些元素满足条件,所以需要不断拉取,看最终是否满足。

您可以使用 dropwhiletakewhile 进行过滤:

from itertools import takewhile,dropwhile

...


fibiter = FibIter()
fibiter_in_range = takewhile(lambda n: n <= 10002000,dropwhile(lambda n: n < 100000,fibiter))

>>> list(fibiter_in_range)
[121393,196418,317811,514229,832040,1346269,2178309,3524578,5702887,9227465]

不过,这基于数字的值进行过滤,而不是它们在生成器中的索引,因为您写道,您想“优雅地创建带有 n 范围为 100000-100020 的斐波那契数的迭代器?”。为了示例,我增加了上限,因为否则它找不到任何元素。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。