我刚看到一个使用网页生成器的Fibonacci系列示例。 这是我看到的例子
def fibonacci(n):
curr = 1
prev = 0
counter = 0
while counter < n:
yield curr
prev, curr = curr, prev + curr
counter += 1
用户可以输入限制'n'。
我的问题是在这里使用发电机的用途是什么? 发电机如何使用户受益? 他获得了什么样的优势,而不仅仅是在这里使用普通的打印信息打印系列?
我同意,如果用户必须将值存储在列表中并稍后处理,则yield可以在运行时生成数字。
在这种情况下,什么可以使用收益?
答案 0 :(得分:1)
生成器而不是函数的优点是它可以保持其状态。
如果您使用了递归函数,计算第5个斐波纳契数就相当于计算第1个,然后计算第1个和第2个,然后计算第1个,第2个和第3个,依此类推,直到第5个。
你可以看到这对大数字来说是怎样的问题;浪费了很多资源。
使用生成器,您计算第1个,并记住它是什么,这样您就不必再次计算它以找到第二个。与功能在返回时停止的功能不同,发电机可以保持状态。因此它计算第一个数字,并在需要时计算第二个数字,然后计算第三个数字,而不会浪费处理能力,因为它不需要每次重新计算整个数据;它记得以前的状态。
关于打印与产量,显然如果你想使用你为其他东西计算的斐波那契数字,你就不能使用打印结果;它只是在屏幕上输出。如果您想生成图表,例如,print
不会,您必须将值传递给您的绘图功能。
答案 1 :(得分:1)
通过产生该值,函数的调用者可以访问中间结果,从而使这个内存有效。
例如,以下内容会为您提供最多n
的所有结果,但要求您先创建一个列表来保存这些值:
def fibonacci(n):
results = []
curr = 1
prev = 0
counter = 0
while counter < n:
results.append(curr)
prev, curr = curr, prev + curr
counter += 1
return results
如果我的代码询问{{1}},那不仅需要很长时间才能生成,而且还需要重要的内存量。
生成器选项使调用者可以立即访问结果,这意味着他们可以在程序的另一部分中使用一个中间结果。)
这使得发电机功能更加灵活多变。您可以对斐波那契结果求和,而无需重写生成器,例如:
fibonacci(10 ** 9)
这仍然是内存效率,在产生结果时进行求和,所有10个结果都不会存在于内存中。只需要当前的中间值,以及到目前为止的总和。
如果您只想打印值,可以循环执行:
sum_of_fibonacci_10 = sum(fibonacci(10))
并且代码仍然有效,我们仍然不必更改生成器函数。
因此,生成器可让您维护和共享中间状态,从而节省内存。这也可以通过类来完成,但生成器更具可读性。以下内容也是如此,但并不容易理解:
for next_value in fibonacci(10):
print(next_value)
答案 2 :(得分:0)
使用生成器可让您在闲暇时生成序列一次的“提示”。您可以检索并打印结果,但不需要。
函数中的普通ol'循环将一直运行,直到达到破坏条件 - 或者永远 - 并且没有任何特殊的铃声和口哨声,阻止代码的执行直到循环终止。
这意味着一旦你杀了解释器,一个无限循环只会停止,很快就会 杀死它,因为它会开始像吃疯狂计算一样吃掉资源非常高的金额。
产生暂停之间的暂停和返回该值,而不是像print()那样只显示它。这意味着你可以检索第n个斐波纳契数,做一些其他的东西五分钟,然后检索第n + 1个数字。