1. 程式人生 > 實用技巧 >Intellij-解決報錯:import sun.misc.BASE64Decoder無法找到

Intellij-解決報錯:import sun.misc.BASE64Decoder無法找到

1.什麼是生成器:可以理解為一種資料型別,這種資料型別實現了迭代器協議(其他的資料型別需要呼叫自己內建的__iter__ 方法),所以生成器就是可迭代物件

2.生成器分類在python中的表現形式:(python有兩種不同的方式提供生成器)

  (1)生成器函式:常規函式定義,但是,使用yield語句而不是return語句返回結果。yield語句一次返回一個結果,在每個結果中,掛起函式的狀態,以使下次從他離開的地方繼續執行

def test():
    print('開始生孩子了')
    yield ''
    print('開始生兒子了')
    yield '兒子'
    yield
'孫子' res = test()                            res呼叫了次函式,此時res就相當於一個生成器,支援__next__方法,同時也可以用for迴圈去遍歷它 即 for i in res:print(i) 會將所有內容列印(生孩子---孫子)         print(res) print(res.__next__())               print(res.__next__()) 執行結果: <generator object test at 0x00000198BF0A30F8>        呼叫函式,相當於返回一個地址 (生成器) 需要通過res.__next__()來顯示
開始生孩子了                            我 開始生兒子了 兒子                                從執行結果可以得知,yield返回了一個值,相當於return,其與return不同之處在於yield會儲存當前函式的執行狀態,所以第二次執行print(res.__next__())
                                  是從print(‘開始生兒子了’)開始,並在yield ‘兒子’ 處停止並返回值

      賣包子例項

def pro_baozi():
    
for i in range(100): print('正在生產包子') yield '第 %s屜包子生產出來了' %i print('\n') print('第 %s屜包子賣出去了'%i) pro_g = pro_baozi()               pro_g呼叫了函式,此時pro_g就可看作是一個生成器,此時它支援__next__方法 baozi1 =print(pro_g.__next__()) baozi1 =print(pro_g.__next__()) baozi1 =print(pro_g.__next__()) 執行結果: 正在生產包子 第 0屜包子生產出來了        函式執行到第一個 yield 暫停並返回值,第二次執行從當前位置開始直到再一次碰到 yield 暫停並返回值                   此處開始到下一次換行前是第二次呼叫的結果,因為yield會保留函式的執行狀態,所以在第二次呼叫後,先執行print('\n'),因為print自帶換行,因此執行此語句換行了兩次 第 0屜包子賣出去了 正在生產包子 第 1屜包子生產出來了 第 1屜包子賣出去了 正在生產包子 第 2屜包子生產出來了

  (2)生成器表示式:類似於列表推導,但是,生成器返回按需產生結果的一個物件,而不是一次構建一個結果列表

    三元表示式

name = '焦國華'
res = '帥哥'   if name == '焦國華'  else  '沙雕'        這種形式就是三元表示式
print(res)  
執行結果:

帥哥



    列表解析

l = ['雞蛋%s' %i for i in range(10)]      這種形式就稱為列表解析,實際上也是[ ]內是一個二元表示式   也可以寫為 l = ['雞蛋%s' %i for i in range(10)  if i >5]   執行輸出['雞蛋 0', '雞蛋 1', '雞蛋 2', '雞蛋 3', '雞蛋 4']
print(l)
執行結果:['雞蛋0', '雞蛋1', '雞蛋2', '雞蛋3', '雞蛋4', '雞蛋5', '雞蛋6', '雞蛋7', '雞蛋8', '雞蛋9']

    總結:

    (1)生成器表示式 把列表解析的 [ ] 換成()得到的就是生成器表示式

laomuji = ('雞蛋%s' %i for i in range(10))
print(laomuji)
print(laomuji.__next__())
print(laomuji.__next__())
執行結果:
<generator object <genexpr> at 0x000001AFF8B8F048>
雞蛋0
雞蛋1

    (2)列表解析與生成器表示式都是一種便利的程式設計方式,只不過生成器表示式更節省記憶體

    (3)python不但使用迭代器協議,讓for迴圈變得更加通用。大部分內建函式,也是用迭代器協議訪問物件。例如,sum函式是python的內建函式,該函式使用迭代器協議訪問物件,而生成器實現了

      迭代器協議,所以,我們可以直接這樣計算一系列值的和:

sum(x ** 2   for x in range(4))      即內部可以直接寫一個生成器表示式,因為生成器表示式滿足迭代器協議

      而不用多此一舉先構造一個列表

sum([x ** 2   for x in range(4)])

3.生成器總結:

  (1)語法上和函式類似:生成器函式和常規函式幾乎是一樣的,他們都是使用def語句進行定義,差別在於,生成器使用 yield 語句返回一個值,而常規函式使用 return 語句返回一個值

  (2)自動實現迭代器協議:對於生成器,python會自動實現迭代器協議,以便應用到迭代背景中(如for迴圈、sum()函式)。由於生成器自動實現了迭代器協議,所以,我們可以呼叫它的__next__

    方法,並且,在沒有值可以返回的時候,生成器自動生成StopIteration異常

  (3)狀態掛起:生成器使用yield語句返回一個值,yield語句掛起該生成器函式的狀態,保留足夠的資訊,以便之後從離開他的地方繼續執行

優點::生成器的好處之一