午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

為什么要使用 Python 生成器?該如何使用 Python 生成器?

 我的人生寶庫 2019-12-17

自從 PEP 255 引入生成器以來,它就是 Python 中重要的一部分.

生成器允許你定義一個有迭代器行為的函數(shù).

它允許程序猿更快,更簡單并且以一個干凈的方式創(chuàng)建一個迭代器.

那么什么是迭代器呢,你或許會問?

iterator 迭代器是一個可以被迭代的(循環(huán))對象。它可以抽象為一個裝著數(shù)據(jù)同時有著可迭代對象的行為的容器?;蛟S你已經(jīng)每天在使用一些可迭代的對象:諸如字符串,列表,字典或其它名字的對象.

一個迭代器是一個實(shí)現(xiàn)了迭代器接口 Iterator Protocol 的類。這個接口為類提供了兩個方法: __iter__ 和 __next__.

嗯~回到上一步。你為什么想要創(chuàng)建一個迭代器呢?

節(jié)省內(nèi)存空間

當(dāng)實(shí)例化后,迭代器并不會計算它每一個項的值,他們只會等你訪問這些項的時候采取計算。這也就是眾所周知的惰性求值。

當(dāng)你有一個非常大的數(shù)據(jù)集需要計算時,惰性求值是很有用處的。它允許你馬上就能開始使用數(shù)據(jù),盡管整個數(shù)據(jù)集還在計算中。

假設(shè)我們想要獲得小于某個最大值的所有素數(shù)。

我們先定義一個函數(shù),它可以檢查一個數(shù)字是否為素數(shù):

def check_prime(number): for divisor in range(2, int(number ** 0.5) + 1): if number % divisor == 0: return False return True

然后,我們定義一個迭代器類,包含__iter__ 和 __next__ 方法。

class Primes:    def __init__(self, max):        self.max = max        self.number = 1    def __iter__(self):        return self    def __next__(self):        self.number += 1        if self.number >= self.max:            raise StopIteration        elif check_prime(self.number):            return self.number        else:            return self.__next__()

Primes 類通過給定一個最大值來實(shí)例化。如果下一個素數(shù)比最大值 max 還要大,迭代器就會拋出一個 StopIteration 異常來把迭代器停掉。

當(dāng)我們請求迭代器中的下一個元素時,它會給 number 加 1 并檢查這個數(shù)字是否為素數(shù)。如果不是,它會再次調(diào)用__next__直到 number 成為素數(shù)。一旦如此,迭代器就將這個數(shù)字返回。

通過使用迭代器,我們并不會在內(nèi)存中創(chuàng)建一個包含很多素數(shù)的列表。相反,我們將會在每次請求下一個素數(shù)時才去生成它。

讓我們來試一試:

primes = Primes(100000000000)print(primes)for x in primes: print(x) ......<__main__.Primes object at 0x1021834a8>235711...

對 Primes 對象的每一次迭代都調(diào)用了 __next__ 來生成下一個素數(shù)。

迭代器只可以被迭代一輪。如果你嘗試再迭代 primes 一輪,它將不會返回任何值,表現(xiàn)得就像個空列表。

既然我們已經(jīng)知道了什么是迭代器,以及怎么制作一個迭代器,我們接下來將繼續(xù)來看看生成器。

生成器

回想下,生成器函數(shù)允許我們以一種更簡單的方式來創(chuàng)建迭代器。

生成器給 Python 引入了 yield 聲明。它用起來有點(diǎn)像 return,因?yàn)樗鼤祷匾粋€值。

區(qū)別在于 yield 會保存函數(shù)的狀態(tài)。在函數(shù)下一次被調(diào)用時,將會從其離開的地方繼續(xù)執(zhí)行,并且變量值也與它之前執(zhí)行 yield 操作前相同。

如果把我們的 Primes 迭代器轉(zhuǎn)換為生成器,它看起來會像這樣:

def Primes(max):    number = 1    while number < max:        number += 1        if check_prime(number):            yield numberprimes = Primes(100000000000)print(primes)for x in primes:    print(x)......<generator object Primes at 0x10214de08>235711...

現(xiàn)在真是太 pythonic 了!我們還能再給力點(diǎn)嗎?

當(dāng)然!我們可以使用 PEP 289 中介紹的生成器表達(dá)式。

這相當(dāng)于是生成器的列表推導(dǎo)式。它用起來與列表推導(dǎo)式相同,不過表達(dá)式由 () 包裹而不是 []。

下面的表達(dá)式可以代替我們上面的生成器函數(shù):

primes = (i for i in range(2, 100000000000) if check_prime(i))print(primes)for x in primes: print(x)......<generator object <genexpr> at 0x101868e08>235711...

這就是 Python 生成器的美妙之處。

總結(jié)...
  • 生成器允許你以一種非常 pythonic 的方式來創(chuàng)建迭代器。
  • 迭代器允許惰性求值,只有在請求下一個元素時迭代器對象才會去生成它。這對于非常大的數(shù)據(jù)集是很有用的。
  • 迭代器和生成器都只能被迭代一輪。
  • 生成器函數(shù)比迭代器更好。
  • 生成器表達(dá)式比迭代器更好(只在簡單情況下如此)。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多