python中的函数返回后如何记住其值?

How does a function in Python remember its values after it returns?

本问题已经有最佳答案,请猛点这里访问。

警告:新手问题

我似乎一直在考虑函数作为一个食谱。在我的世界里,程序是一个配方盒,一些配方(函数)调用其他配方(其他函数)。处理器开始执行主配方,将指令写入RAM并通过它们工作。比如,早餐薄饼。你称之为茱莉亚·查尔兹的早餐薄饼配方。你得做一次煎饼面糊。然后,当你还有薄饼面糊的时候,你反复地做薄饼。同时,你也可以制作各种水果制品。

我显然不明白。我刚刚通过pythontutor.com运行了python wiki解决方案来解决ProjectEulerProblem 2(甚至小于400万的fibonacci数字之和)。我想我发生了什么事。似乎每次你变出一个食谱,你不只是使用同一个处理器,你会得到一个有一些罐子的侏儒来完成这个功能。pots是变量,gnome计算出他的配方,如果调用函数期望返回值,gnome会向调用者显示这些pot的内容。然后调用者可以返回,找出更多的东西,并向调用者显示返回值。

所以假设艾尔打电话给鲍勃做薄饼。鲍勃做面糊,叫查理做。查理做了一个薄饼,把薄饼端给鲍勃,鲍勃把它给艾尔,然后回到查理身边。谁还活着!艾尔不知道鲍勃把查理藏在厨房里了,但即使查理做了第一道薄饼,他仍然在厨房里,知道如何做薄饼,也知道他还剩下多少薄饼面糊。尽管他已经把第一张薄饼还了。

有人能帮我清理一下吗?

这是python wiki的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 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


一个简单的答案。

如果您有一个生成值序列的函数,您可以使用yield在generator中转换它。

1
2
3
4
5
6
7
8
9
10
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,这是你可以迭代的东西。

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

1
2
3
4
5
6
7
8
9
10
11
def inf():
    x = -1
    while True:
        x = x + 1
        yield x

for i in inf():
    if i < 10:
        print(i)
    else:
        break

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


原则上,您的第一个假设是正确的:只有在执行函数时,函数的变量才可用。然而,在您的案例中,您使用的是yield语句。因此,函数调用返回迭代器,当调用迭代器时,它返回下一个yield语句的值。

有关迭代器是什么和做什么的进一步解释,请查看本文。