Here我找到了一个很好的方法,如何使用延迟输出的技术计算数字序列。
我决定使用相同的技术来解决Project Euler中的第二个问题。
代码:
#Answer: 4613732
from itertools import *
import operator
seeds = [1,2]
def deferred_output():
for i in output:
yield i
result,a1,a2 = tee(deferred_output(),3)
paired = map(operator.add,a1,islice(a2,1,None))
output = chain(seeds,paired)
cropped = takewhile((4000000).__gt__,result)
evened = filter(lambda x: x%2==0,cropped)
print(sum(evened))
代码在Python 3.x中完美运行
但是当我尝试在Python 2.x中运行它时,出现以下错误:
Traceback (most recent call last):
File "C:\Documents and Settings\Oleg\Мои документы\_Мои документы\_SyncedWithFlashDrive\Программирование\Project Euler\2\1.py", line 14, in <module>
paired = map(operator.add,a1,islice(a2,1,None))
File "C:\Documents and Settings\Oleg\Мои документы\_Мои документы\_SyncedWithFlashDrive\Программирование\Project Euler\2\1.py", line 9, in deferred_output
for i in output:
NameError: global name 'output' is not defined
这意味着延迟输出在Python 2.x中不起作用
为什么?
答案 0 :(得分:2)
以下代码有效:
from itertools import *
import operator
seeds = [1,2]
def deffered_output():
for i in output:
yield i
result,a1,a2 = tee(deffered_output(),3)
paired = imap(operator.add,a1,islice(a2,1,None)) # change 2 (imap)
output = chain(seeds,paired)
cropped = takewhile(lambda x: x <= 4000000,result) # change 1 (lambda)
evened = filter(lambda x: x%2==0,cropped)
print(sum(evened))
我需要做两处修改:
首先,takewhile的参数需要是lambda,因为2.7中的整数不具有__gt__
等方法。
第二,更重要的是,python 3中的map()
是懒惰的 - 它返回一个后来完成工作的生成器。相比之下,在python 2.7中,它非常渴望 - 它可以直接完成工作并返回一个列表。
所以,在python 2.7中,map()
触发代码的评估,代码通过各种生成器回调,直到它评估deffered_output()
函数。这一切都发生在之前定义output
的行。所以有一个错误,因为output
未定义。
然而,在python 3中(或在python 2.7中使用imap()
时)该行创建了另一个生成器,在sum()
中评估事物之前,它实际上并没有完成工作(和到那时,output
已定义,因此可以对deffered_output
进行评估。
如果不清楚,那么您需要在python中了解有关generators的更多信息。
ps并不重要,但它让我疯狂地看着它:它推迟了#34;而不是&#34; deffered&#34;!