【问题标题】:Deferred_output for cyclical iteration in Python 2.xPython 2.x 中循环迭代的 Deferred_output
【发布时间】:2012-03-11 16:05:07
【问题描述】:

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 中不起作用

这是为什么呢?

【问题讨论】:

    标签: python python-3.x python-2.x


    【解决方案1】:

    以下代码有效:

    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() 中评估事情(到那时,@987654331 @ 已定义,因此可以对 deffered_output 进行评估)。

    如果不清楚,那么您需要了解更多关于 python 中的 generators 的信息。

    ps 不重要,但看着它让我发疯:它是“延迟”,而不是“延迟”!

    【讨论】:

    • 谢谢。你是怎么追踪到的?我认为它与“outmost-iterable-precomputation”问题有关。所以我认为 Python 3.x 中的行为已经改变(尽管无法找到足够的信息)。所以我什至没有考虑过map&lt;-&gt;imap(虽然最初在写代码的时候我写了imap,因为一个习惯,只在出现异常时才改成map)。
    • 感谢其他更正! __gt__ 我使用主要是因为我担心lambda 会减慢一切。
    • 关于deferred的拼写。对此感到抱歉。我在写这个问题时很小心(希望里面没有这个词的拼写错误),但是代码只是通过剪贴板复制的。这就是我马虎的地方。我编辑了帖子以更正所有拼写错误。
    • 嗯,首先我花了很长时间试图弄清楚它与范围界定的变化有何关系,但我在 python 3 发行说明中找不到任何内容,然后我注意到堆栈跟踪来自map(),直到稍后才评估该代码。最后我意识到有人在您获得代码的原始页面中指出了这一点!不用担心延期:o)
    猜你喜欢
    • 1970-01-01
    • 2017-04-28
    • 2016-01-02
    • 2012-06-27
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多