python進階學習之 yield

背景介紹    

 最近在學習Tornado的async編程技巧, 發現yield是基礎, 爲了彌補以前對他的疏忽, 特此發文深刻加深其印象, 以及提升其做用。python

基礎概念

        yield的做用就是掛起程序, 而且返回yield以後的值。 舉個很簡單的例子:express

​
#-*- coding: utf-8 -*-

def gen():
    b = yield "yield value"
    print "StateA ", b

generator = gen()
print generator.next()

​

        對上述程序進行簡單的分析:編程

  • 執行輸出的結果:yield value, 
  • generator = gen() , 建立一個生成器, (含有yield的函數體, 其函數調用的結果就是生成一個生成器, 不會執行其函數體。)
  • generator.next(),   只有當生成器的next函數被第一次觸發, 函數體纔會被執行, 到第一個yield處掛起。程序稍做修改來驗證一下:
#-*- coding: utf-8 -*-

def gen():
    print "enter gen()"
    b = (yield "yield value")#pause
    print "StateA ", b

generator = gen()
print "created a generator"
print generator.next()

執行結果:async

created a generator
enter gen()
yield value函數

  • 若是生成器的next函數被第二次觸發(再次例子中), 因爲沒有yield了, 會在函數體執行結束以後拋出異常。  
#-*- coding: utf-8 -*-

def gen():
    b = (yield "yield value")#pause
    print "StateA ", b

generator = gen()
print generator.next()
print generator.next()

執行結果:學習

yield value
StateA  None
Traceback (most recent call last):
  File "yield-sample.py", line 9, in <module>
    print generator.next()
StopIterationspa

  • b = (yield "yield value") ,  從上述的執行結果中看, b的值爲None, 同時應該注意到, 複製動做是在第二次next的時候被調用到的。
  • 咱們再想, 如何讓yield expression有返回值,  而且此返回值是從外圍穿入進去的, 這正是generator.send(value)要作的事情:
#-*- coding: utf-8 -*-

def gen():
    b = (yield "yield value")#pause
    print "StateA ", b

generator = gen()
print generator.next()
print generator.send("yield expression return value")

執行結果code

yield value
StateA  yield expression return value
Traceback (most recent call last):
  File "yield-sample.py", line 9, in <module>
    print generator.send("yield expression return value")
StopIterationutf-8

  •  下面的代碼是否是也是能夠的?generator

#-*- coding: utf-8 -*-

def gen():
    b = (yield "yield value")#pause
    print "StateA ", b

generator = gen()
print generator.send("yield expression return value")

    其實沒啥, 就是去掉了 print generator.send(None)

執行結果

Traceback (most recent call last):
  File "yield-sample.py", line 8, in <module>
    print generator.send("yield expression return value")
TypeError: can't send non-None value to a just-started generator

這是爲何? 這要追述一下generator.send(value)的做用: 給yield表達式傳值, 也就是說讓(yield expression) = value,  (注意: 是剛剛掛起的yield); 爲了達到這個目的, 在此以前必定要讓generator掛起一次才行, 因此在此以前必須有generator.next()/send(None) 的調用。

總結

帶有yield表達式的函數在運行的時候就是一個generator(生成器), 今生成器有兩個對外的函數, next()和send(value)

  • 相同點

generator.send(None) 和generator.next() 做用是相同的。 都是驅使生成器從一個yield向下一個yield去執行函數體, 而後掛起返回yield後面的表達式。

  • 不一樣點

1.   generator.send(value)  要在generator.next()/send(None)以後執行,  他的做用: 返回當前掛起yield expression = value, 若是讓當前的yield掛起, 必須執行一次next()/send(None)。

2.  其實最大的不一樣就是, send能夠把函數外的value能傳到到函數中, 而next不能。

相關文章
相關標籤/搜索