2013年5月4日 星期六

python yield 語法與 generator 物件介紹

    這篇介紹 yield 語法以及用來維護 yield 行為的 generator 物件。
    事實上,yield 和 return 很像,只是當函數呼叫 return 時,該函數 call stack (python 中是 frame) 就會被清除,程式主導權回到呼叫該函數的手上。 而 yield 會把程式主導權交給呼叫該函數的手上,但是他不會把函數的 call stack 清除,因此下次呼叫時,可以從上次未執行的部分開始執行,而不是重新建立一個新 stack。



def return_fun():
    a = 1
    b = 1
    return a

print return_fun()
print return_fun()

    上面這段程式碼,每次呼叫 return_fun 時,都是從 a = 1 開始執行,然後遇到 return 就結束了。所以執行流程像這樣

     當有函數裡面有用到 yield 這個關鍵字時,事情就變得很不一樣了。



def yield_fun():
    a = 1
    b = 1
    yield a
    yield b
    
print yield_fun()

    當你執行上面這段程式碼時,你會發現他回傳給你的居然是 generator 物件。那要怎麼執行 yield_fun 裡面的 code 呢? 答案是使用 generator 的 next 方法。


def yield_fun():
    a = 3
    b = 2
    yield a
    c = 4
    yield b
    
generator = yield_fun()
print generator.next()
print generator.next()

    當使用者第一次呼叫 generator 的  next 方法時,他會從 a = 3 開始執行,直到遇到 yield。python 會回傳 yield 後面接的東西(就像 return ),之後再把現在的 call stack( python 中是 frame),儲存在 generator 的 gi_frame 屬性中。

    當使用者第二次呼叫 generator 的  next 方法時,他不會建立一個新的 call stack,而是從  generator 的 gi_frame 屬性中取出之前的 call stack。因此,程式會從 c = 4 開始執行(不是從 a = 3喔,如果是 function 的話,是從 a = 3 開始執行)。直到遇到 yield 或是 return 為止。遇到 yield 表示下次還可以再呼叫一次 next 方法。遇到 return 則表示 這個 generator 已經沒東西了。無法再呼叫 next 了。執行流程像這樣。

    事實上, yield 除了可以把資料回傳給呼叫者外,他也可以從呼叫者接受資料。向下面的程式碼。


def yield_fun():
    a = 3
    b = 2
    
    b = yield a
    yield b
    

generator = yield_fun()
print generator.next()
print generator.send(8)

    上面這段程式碼, yield 除了把 a 的值回傳給呼叫者外,他還會從呼叫者那邊接受一個值,把 b 的值指派成呼叫者給的參數。

    generator 打破函數執行完後, call stack 就會被清除的限制(因為 generator 把 call stack 存在 gi_frame 屬性,所以下次執行時,還知道之前的狀態)。

5 則留言:

  1. 請問有Python3的內容嗎?因為Python3的運作方式已經不一樣了。

    回覆刪除
    回覆
    1. def yield_fun():
      a = 3
      b = 2

      b = yield a
      yield b


      generator = yield_fun()
      print(next(generator))
      print(generator.send(8))

      刪除
  2. If you resolve to 1xbet play free online slots for real money, you’re guaranteed timely payouts, honest profitable odds, and legitimate bonuses that give new sign-ups a big head-start. Ignition Casino started its operations in 2016, which was unknown for the primary two years. As people started exploring games to help them earn from home, this on line casino made it to the highest because of its large variety of premium games.

    回覆刪除