瞭解生成器

什麼是生成器

在學習生成器以前,首先咱們要知道什麼是生成器? 在python中一邊循環一邊計算的機制就是生成器(generator)python

生成器做用

知道了什麼是生成器以後,咱們須要知道爲何要有生成器呢? 也就是說這種一邊循環一邊計算的機制有什麼用處呢?算法

咱們知道列表中全部的數據都存在內存中,若是數據不少的話將會特別消耗內存。先不說內存有沒有這麼大,假設咱們僅僅須要訪問前面幾個元素,那後面元素所佔用的空間豈不是都白費了嗎。函數

因此這個時候若是列表中的元素可以按照某種算法自動推算出來呢,是否是就沒必要建立完整的列表,能夠節省大量的內存空間了。因此若是又想節省內存,又須要用到不少數據就能夠使用生成器。學習

建立生成器

經過相似列表生成式方式實現

建立生成器有好幾種方法,最簡單一種就是把一個列表生成式的[]改爲(),這樣就能直接建立一個生成器:code

# 列表生成式
list = [x for x in range(10)]
print(list)  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 生成器
generator = (x for x in range(10))
print(generator)  # <generator object <genexpr> at 0x0000000002131A20>

咱們能夠直接經過print(list),將list中全部元素打印出來。可是print(generator)打印出來的倒是一個對象,若是咱們想要打印出生成器中的元素要怎麼幫?有兩種方式:對象

  • 一:經過next()方法一個一個元素打印:
generator = (x for x in range(10))

print(next(generator))  # 0
print(next(generator))  # 1
print(next(generator))  # 2

每次調用一次next()方法就計算出下一個元素的值,直到超出最後一個元素時,則會拋出StopIteration錯誤。 這種方法只能一個一個元素打印,若是隻須要前面幾個元素,用這樣方法恰好。若是須要打印不少元素,這個方法就太不方便了。這時候咱們能夠用第二種方法。blog

  • 二:使用for循環,由於生成器也是可迭代對象。
generator = (x for x in range(5))
for g in generator:
    print(g)

# 輸出:
0
1
2
3
4

這樣不只能夠一次性將全部元素打印出來,且經過for循環打印不須要擔憂會發生StopIteration異常。內存

這樣看起來和列表生成式沒差?但咱們要注意列表生成式是直接將全部元素存在了內存空間中,這樣佔用了大量內存。而生成器並非當即將結果寫入內存, 而是保存的一種計算方式, 經過不斷的計算, 能夠獲取到相應的位置的值,因此佔用的內存僅僅是對計算對象的保存。get

方法二:經過函數來實現

若是推算的算法比較複雜,用相似列表生成式的for循環沒法實現的時候,還能夠用函數來實現。只須要在函數中定義一個yield語句就行。 因此帶有 yield 的函數再也不是一個普通函數,而是一個生成器。yield至關於 return 返回一個值,而且記住這個返回的位置,下次迭代時,代碼從yield的下一條語句開始執行。generator

def gen_yield():
    for i in range(3):
        yield i

g = gen_yield()
print(next(g))  # 0
print(next(g))  # 1
print(next(g))  # 2
print(next(g))  # 報錯:StopIteration

# 生成器函數每一次next()迭代,會返回當前yield的值,且在此處暫停,下一次next()迭代,
# 從上一次的yield處開始,向下執行,且依然在下一次的yield中暫停

# for循環迭代
for i in g:
    print(i)

# 輸出:
0
1
2

上述中gen_yield()其實就是一個生成器函數,若是咱們想要獲得這個函數中的返回值,一樣能夠經過next()方法或者for循環迭代來獲得。

參考:https://www.9xkd.com/

相關文章
相關標籤/搜索