2013-04-10 69 views
7

警告:極端新手問題Python中的函數在返回後如何記住它的值?

我似乎一直在想功能作爲一個配方。在我的世界裏,這個程序是一個食譜盒,一些食譜(功能)要求其他食譜(其他功能)。處理器通過將指令寫入RAM並通過它們工作來開始執行主配方。就像早餐薄餅一樣。你叫Julia Childs的早餐薄餅食譜。你必須做一次縐麪糊。然後,當你還有縐紗時,你反複製作薄餅。同時,您可以製作各種水果製劑。

那麼,我顯然不明白。我通過pythontutor.com將python wiki解決方案運行到Project Euler Problem 2(即使斐波納契數字總和小於400萬)。我覺得有些事情發生在我身上。看起來每次你召喚一個食譜,你不只是使用同一個處理器,你會得到一個侏儒來處理這個功能。罐子是變量,侏儒計算出他的食譜,如果調用函數期望返回值,侏儒向調用者顯示這些罐子的內容。然後調用者可以返回,找出更多的東西,並向其調用者顯示返回值。

所以讓我們說艾爾叫鮑勃做薄餅。鮑勃讓麪糊打電話給查理做飯。查理烹製縐紗,將縐製品送給鮑勃,鮑勃將其送給艾爾,然後返回查理。誰還存在!艾爾並不知道鮑勃把查理藏在廚房裏,但即使查理做出第一道可麗餅之後,他仍然在廚房裏,知道如何製作縐紗,並且知道他已經留下了多少縐紋面糊。儘管他已經回來了第一個縐紗。

有人可以幫我解決這個問題嗎?

下面是從Python維基

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

+6

您的困惑是可以理解的。除了'yield'關鍵字之外,程序確實按照您認爲應該(有點)的方式工作。正如你所描述的,「產量」在水槽下面存放一個侏儒。當你正在學習時,你可能會選擇避免「收益」,或者你可能會選擇專門閱讀它。 – 2013-04-10 15:25:15

+1

你在這裏有*生成器*。每當他們遇到'yield'關鍵字時,發電機就被置於冰面上,將控制權交還給他們。 – 2013-04-10 15:26:27

+0

http://www.jeffknupp.com/blog/2013/02/14/drastically-improve-your-python-understanding-pythons-execution-model/ – Torxed 2013-04-10 15:26:30

回答

2

這是因爲這些功能不是功能,而是generatorsyield語句返回一個值,但不從函數返回。每次您在生成器上調用next時,它會從最後一次調用繼續執行生成器,直到它再次達到yield聲明。

1

原則上,您的第一個假設是正確的:函數的變量只有在函數執行時纔可用。但在您的情況下,您正在使用yield聲明。結果函數調用返回一個迭代器,該迭代器在被調用時返回下一個yield語句的值。

查詢this post瞭解迭代器是什麼和做什麼的進一步解釋。

2

簡化的答案。

如果您具有生成值序列的函數,則可以使用yield將其轉換爲generator

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 
相關問題