python生成器

生成器是python一個比較高級的特性,理解也比較抽象
產生生成器的方法有幾種:
第一種

a=(i for i in range(10))
print(a)  # ----- generator object <genexpr> at 0x0000022BD830E410
print(type(a)) # ---- generator

這時候a變成了一個生成器
(注:使用a=[i for i in range(10)]會產生一個列表,注意區分[]和()的區別)
第二種:使用yield關鍵字

def foo():
     yield 1
a=foo()

使用關鍵字yield,也可以將函數變成生成器

生成器有next(python2爲next()方法)和send()方法
可以看到,每次我們調用next()方法時,都會返回下一個值
然後下次調用再從上次結束的地方繼續調用
這樣做的好處是不用返回一整個列表,非常節省字符空間
比如在python2環境中,有range和xrange兩個方法(在python3中取消了xrange,直接使用range,相當於python3的rangge就是python2的xrange方法)
xrange就是一個迭代器
在python2的環境中運行
sum(x for x in range(100000000))
可以觀察電腦資源使用情況,我這CPU直接100%,內存%100,直接重啓了
因爲range是一次生成1-100000000的列表
而sum(x for x in xrange(100000000))可以看到系統資源基本沒有什麼佔用
因爲xrange是一次次地調用值,所以資源佔用少
生成器函數send
next其實就是send(None)

def count(n):
    for i in range(n):
        yield i
        a=yield i
        print(a)

gen=count(5)

gen.send(“test”)則會打印出test
可以看到gen.next()和gen.send(None)效果是一樣的
其實next源碼就是send(None)的實現
另外gen.close()方法即爲關閉生成器,再調用next會拋出StopIteration異常
既然 send裏面的值可以傳給(yield),那麼我們可以用這個來實現簡單的簡單的生產消費者,也是簡單協程的實現

def consumer():
    i = 0
    while True:
        tmp = yield i
        if tmp is not None:
            print("我是消費者: {}".format(tmp))


def producer(gen, n):
    gen.__next__()
    for i in range(n):
        print("我是生產者: {}".format(i))
        gen.send(i)


gen = consumer()
producer(gen, 5)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章