1. 程式人生 > >python三大神器之生成器

python三大神器之生成器

生成器Generator:

  本質:迭代器(所以自帶了__iter__方法和__next__方法,不需要我們去實現)

  特點:惰性運算,開發者自定義

在python中有三種方法來獲取生成器:

        1.通過生成器函式

        2.通過各種推導式來實現生成器

        3.通過資料的轉換獲取生成器

一個包含yield關鍵字的函式就是一個生成器函式。yield可以為我們從函式中返回值,但是yield又不同於return,return的執行意味著程式的結束,呼叫生成器函式不會得到返回的具體的值,而是得到一個可迭代的物件。每一次獲取這個可迭代物件的值,就能推動函式的執行,獲取新的返回值。直到函式執行結束。

def func():
    print('hello')
    yield 1
    print('world')
    yield 2

g = func()       # 呼叫"生成器函式"
a = g.__next__()
print(a)          # a  generator(生成器)
b = g.__next__()
print(b)

# yield關鍵字的特點: 可以記錄當前函式中執行的位置,下一次繼續執行
# next和yield是一對搭檔 : next開始函式的執行 yield停止函式的執行

列表推導式的常用寫法:[結果 for 變數 in 可迭代物件]

生成器表示式和列表推導式的語法基本上是一樣的,只是把[ ]替換成( )

倆個的區別:

        列表推導式比較耗記憶體,一次性載入.生成器表示式幾乎不佔用記憶體,使用的時候才分配

        和使用記憶體

 

lst = [i for i in range(10)]
print(lst)
#結果:
#[0,1,2,3,4,5,6,7,8,9]
g= (i for i in range(10))
print(g)
#結果:
#<generator object <genexpr> at 0x106768f10>
#列印的結果就是一個生成器. 我們可以使用for迴圈來迴圈這個生成器: for i in g: print(i)

send方法:send和__next__一樣都可以讓生成器執行到下一個yield.

def generator():
    print(123)
    content = yield 1
    print('=======',content)
    print(456)
    yield2

g = generator()
ret = g.__next__()
print('***',ret)
ret = g.send('hello')   #send的效果和next一樣
print('***',ret)

#send 獲取下一個值的效果和next基本一致
#只是在獲取下一個值的時候,給上一yield的位置傳遞一個數據
#使用send的注意事項
    # 第一次使用生成器的時候 是用next獲取下一個值
    # 最後一個yield不能接受外部的值

 

生成器的應用:監聽檔案的輸入,對於檔案中隨時輸入的內容進行自動化展示

import time


def tail(filename):
    f = open(filename)
    f.seek(0, 2) #從檔案末尾算起
    while True:
        line = f.readline()  # 讀取檔案中新的文字行
        if not line:
            time.sleep(0.1)
            continue
        yield line

tail_g = tail('tmp')
for line in tail_g:
    print(line)