11

警告:极端新手问题

我似乎一直在将函数视为食谱。在我的世界里,程序是一个食谱盒,一些食谱(功能)调用其他食谱(其他功能)。处理器通过将指令写入 RAM 并处理它们来开始执行主配方。比如早餐薄饼。你叫 Julia Childs 的早餐薄饼食谱。你必须做一次可丽饼面糊。然后,当你还有可丽饼面糊时,你会反复制作可丽饼。同时,您可以制作各种水果制品。

好吧,我显然不明白。我刚刚通过 pythontutor.com 运行 python wiki 解决方案来解决 Project Euler Problem 2(偶数斐波那契数小于 400 万的总和)。我认为我发生了一些事情。似乎每次你想出一个食谱时,你不只是使用相同的处理器,你会得到一个带有一些罐子的侏儒来处理那个功能。罐子是变量,gnome 计算出他的配方,如果调用函数期望返回值,则 gnome 将这些罐子的内容显示给调用者。然后调用者可能会返回,找出更多的东西,并向他的调用者显示返回值。

假设 Al 打电话给 Bob 做薄饼。鲍勃做了面糊并叫查理做饭。查理做了一个可丽饼,把可丽饼端给鲍勃,鲍勃把它给了艾尔,然后又回到查理身边。谁还在!艾尔不知道鲍勃把查理藏在厨房里,但即使在查理做了第一个可丽饼之后,他仍然在厨房里,知道如何制作可丽饼,并且知道他还剩下多少可丽饼面糊。即使他已经退回了第一个可丽饼。

有人可以帮我解决这个问题吗?

这是来自 Python wiki 的代码

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

def even(seq):
    for number in seq:
        if not number % 2:
            yield number

def under_a_million(seq):
    for number in seq:
        if number > 1000000:
            break
        yield number   

print sum(even(under_a_million(fib())))

这是http://pythontutor.com/visualize.html

4

3 回答 3

3

一个简化的答案。

如果您有一个生成一系列值的函数,您可以generator使用 yield 将其转换为 a。

def func():
    for i in range(3):
        yield i

list(func()) ==> [0,1,2]

for el in func():
    print(el) # 0
              # 1
              # 2

每次调用 yield 时,函数都会在某处冻结。当它再次被调用时,它会从他的最后一个状态继续,并且不会重新开始(除非它已经完成了元素的消耗)。

如果你调用这个函数,你会得到一个generator,这是你可以迭代的东西。

请注意,这种方式可以迭代无限序列,而无需使用无限内存。

def inf():
    x = -1
    while True:
        x = x + 1
        yield x

for i in inf():
    if i < 10:
        print(i)
    else:
        break
于 2013-04-10T15:43:25.767 回答
2

这是因为这些函数不是函数,而是生成器。该yield语句返回一个值,但不从函数返回。每次调用next生成器时,它都会从上次调用开始继续执行生成器,直到yield再次到达语句。

于 2013-04-10T15:29:11.100 回答
1

原则上,您的第一个假设是正确的:函数的变量仅在函数执行时可用。但是,在您的情况下,您正在使用该yield语句。结果,函数调用返回一个迭代器,该迭代器在调用时返回下一条yield语句的值。

查看这篇文章以获得关于迭代器是什么和做什么的进一步解释。

于 2013-04-10T15:31:33.547 回答