乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      學(xué) Python 怎能不知 yield ?

       風(fēng)聲之家 2021-03-16

      簡(jiǎn)說(shuō)Python 1周前

      以下文章來(lái)源于無(wú)量測(cè)試之道 ,作者無(wú)量測(cè)試之道


       簡(jiǎn)說(shuō)Python推薦 
      來(lái)源|無(wú)量測(cè)試之道
      作者|無(wú)量測(cè)試之道

      引言

      你可能聽說(shuō)過(guò),帶有 yield 的函數(shù)在 Python 中被稱之為 generator(生成器),又或者都沒(méi)關(guān)注過(guò),Python 中還有個(gè) yield 的存在。如果你了解過(guò) Python 中的 yield,那你知道何謂 generator 嗎?

      yield 的概念

      理解yield 的 generator 概念,首先以一個(gè)常見的編程題目來(lái)展示 yield 的概念。

      如何生成斐波那契數(shù)列

      斐波那契(Fibonacci)數(shù)列是一個(gè)非常簡(jiǎn)單的遞歸數(shù)列,除第一個(gè)和第二個(gè)數(shù)外,任意一個(gè)數(shù)都可由前兩個(gè)數(shù)相加得到。用計(jì)算機(jī)程序輸出斐波那契數(shù)列的前 N 個(gè)數(shù)是一個(gè)非常簡(jiǎn)單的問(wèn)題,有些 Python 基礎(chǔ)的小伙伴都可以輕易寫出如下函數(shù):

      第 1 版本:簡(jiǎn)單輸出斐波那契數(shù)列前 N 個(gè)數(shù)

      def createNum(count): 
      n, a, b = 0, 0, 1
      while n < count:
      print b
      a, b = b, a + b
      n = n + 1
      createNum(5)

      執(zhí)行以上代碼,我們可以得到如下輸出:

      1 
      1
      2
      3
      5

      輸出結(jié)果是沒(méi)有問(wèn)題的,但是版本 1 中的寫法是直接在 createNum 函數(shù)中用 print 打印數(shù)字會(huì)導(dǎo)致該函數(shù)可復(fù)用性較差,因?yàn)?createNum 函數(shù)返回 None,其他函數(shù)無(wú)法獲得該函數(shù)生成的數(shù)列。

      要提高 createNum 函數(shù)的可復(fù)用性,最好不要直接打印出數(shù)列,而是返回一個(gè) List。以下是 createNum 函數(shù)改寫后的第二個(gè)版本:

      第 2 版本:輸出斐波那契數(shù)列前 N 個(gè)數(shù)

      def createNum(count): 
      n, a, b = 0, 0, 1
      L = []
      while n < count:
      L.append(b)
      a, b = b, a + b
      n = n + 1
      return L

      for n in createNum(5):
      print n

      該版本中 createNum 函數(shù)返回的 List的結(jié)果如下:

      1 
      1
      2
      3
      5

      改寫后的 createNum 函數(shù)通過(guò)返回 List 能滿足復(fù)用性的要求,但是與此同時(shí)也會(huì)存在一個(gè)明顯的問(wèn)題是:該函數(shù)在運(yùn)行中占用的內(nèi)存會(huì)隨著參數(shù) count 的增大而增大,如果要控制內(nèi)存占用,最好不要用 List 來(lái)保存中間結(jié)果,而是通過(guò) iterable 對(duì)象來(lái)迭代。在每次迭代中返回下一個(gè)數(shù)值,如此:內(nèi)存空間占用很小。因?yàn)槭侵苯臃祷匾粋€(gè) iterable 對(duì)象。

      第 3 版本:使用 yield 輸出斐波那契數(shù)列前 N 個(gè)數(shù)

      def createNum(count): 
      n, a, b = 0, 0, 1
      while n < count:
      yield b # 使用 yield
      # print(b)
      a, b = b, a + b
      n = n + 1

      for n in createNum(5):
      print n

      也可以手動(dòng)調(diào)用 createNum(5) 的 next() 方法(因?yàn)?createNum(5) 是一個(gè) generator 對(duì)象,該對(duì)象具有 next() 方法),這樣我們就可以更清楚地看到 createNum 的執(zhí)行流程:

      第 4 版本:執(zhí)行流程

      def createNum(count): 
      n, a, b = 0, 0, 1
      while n < count:
      yield b # 使用 yield
      # print(b)
      a, b = b, a + b
      n = n + 1


      #使用for循環(huán)來(lái)執(zhí)行createNum()函數(shù),它返回一個(gè)迭代值,下次迭代從yield語(yǔ)句的下一條語(yǔ)句繼續(xù)執(zhí)行
      <!--for n in createNum(5):
      print n-->

      #使用next方法來(lái)執(zhí)行createNum()函數(shù),generator(生成器)對(duì)象具有next()方法
      num = createNum(5)
      print(next(num))
      print(next(num))
      print(next(num))
      print(next(num))
      print(next(num))
      print(next(num))

      運(yùn)行以上代碼,結(jié)果輸出如下:

      1
      1
      2
      3
      5
      Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      StopIteration

      由輸出結(jié)果可發(fā)現(xiàn)在執(zhí)行第 6 個(gè) print(next(num)) 時(shí)拋出一個(gè) StopIteration 的異常,是因?yàn)樵诘?5 個(gè) print(next(num)) 執(zhí)行完時(shí)函數(shù)已經(jīng)結(jié)束,再執(zhí)行第 6 個(gè)print(next(num))時(shí),generator 自動(dòng)拋出 StopIteration 異常,表示迭代完成。在 for 循環(huán)里,無(wú)需處理 StopIteration 異常,循環(huán)會(huì)正常結(jié)束。

      yield 的作用

      簡(jiǎn)單地講,yield 的作用就是把一個(gè)函數(shù)變成一個(gè) generator,帶有 yield 的函數(shù)不再是一個(gè)普通函數(shù),Python 解釋器會(huì)將其視為一個(gè) generator,調(diào)用 createNum(5) 不會(huì)執(zhí)行 createNum 函數(shù),而是返回一個(gè) iterable 對(duì)象!

      在 for 循環(huán)執(zhí)行時(shí),每次循環(huán)都會(huì)執(zhí)行 createNum 函數(shù)內(nèi)部的代碼,執(zhí)行到 yield b 時(shí),createNum 函數(shù)就會(huì)返回一個(gè)迭代值,下次迭代時(shí),代碼從 yield b 的下一條語(yǔ)句繼續(xù)執(zhí)行,而函數(shù)的本地變量看起來(lái)和上次中斷執(zhí)行前是完全一樣的,于是函數(shù)繼續(xù)執(zhí)行,直到再次遇到 yield。

      yield 使用場(chǎng)景

      • 迭代生成數(shù)據(jù)(生產(chǎn)者,數(shù)據(jù)量巨大時(shí)優(yōu)勢(shì)更加明顯,它可以不占用大量?jī)?nèi)存)

      • 接收數(shù)據(jù)(消費(fèi)者)

      • 中斷(協(xié)作式的任務(wù))


      總結(jié)

      一個(gè)帶有 yield 的函數(shù)就是一個(gè) generator,它和普通函數(shù)不同,生成一個(gè) generator 看起來(lái)像函數(shù)調(diào)用,但不會(huì)執(zhí)行任何函數(shù)代碼,直到對(duì)其調(diào)用 next()(在 for 循環(huán)中會(huì)自動(dòng)調(diào)用 next())才開始執(zhí)行。雖然執(zhí)行流程仍按函數(shù)的流程執(zhí)行,但每執(zhí)行到一個(gè) yield 語(yǔ)句就會(huì)中斷,并返回一個(gè)迭代值,下次執(zhí)行時(shí)從 yield 的下一個(gè)語(yǔ)句繼續(xù)執(zhí)行??雌饋?lái)就好像一個(gè)函數(shù)在正常執(zhí)行的過(guò)程中被 yield 中斷了數(shù)次,每次中斷都會(huì)通過(guò) yield 返回當(dāng)前的迭代值。

      yield 的好處是顯而易見的,把一個(gè)函數(shù)改寫為一個(gè) generator 就獲得了迭代能力,比起用類的實(shí)例保存狀態(tài)來(lái)計(jì)算下一個(gè) next() 的值,不僅代碼簡(jiǎn)潔,而且執(zhí)行流程異常清晰。


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

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多