4 迭代器和生成器


一 迭代器函數

1.1 概念 spa

# 凡是可使用for循環取值的都是可迭代的
# 可迭代協議 :內部含有__iter__方法的都是可迭代的,如list,dic,tuple,str,集合,range,文件,等都是可迭代的。
# 迭代器協議 :內部含有__iter__方法和__next__方法的都是迭代器code

1.2 優點
可迭代 最大的優點 節省內存blog

迭代器優點:
1節省內存
2取一個值就能進行接下來的計算 ,而不須要等到全部的值都計算出來纔開始接下來的運算內存

1.3 例子generator

 1 這兩個都是可迭代的,都會取到1,2,3
 2 
 3 lst_iter = [1,2,3].__iter__()
 4 print(lst_iter.__next__())
 5 print(lst_iter.__next__())
 6 print(lst_iter.__next__())
 7 
 8 
 9 for i in [1,2,3]:   
10     print(i)

 

 

二 生成器
2.1 概念
生成器 Generator
# 本身寫的迭代器 就是一個生成器
# 兩種本身寫生成器(迭代器)的機制:生成器函數 生成器表達式it

凡是帶有yield的函數就是一個生成器函數for循環

2.2優點class

一樣是節省內存變量

2.3 例子(生成器函數)

 1 # 生成器函數的調用不會觸發代碼的執行,而是會返回一個生成器(迭代器)
 2 # 想要生成器函數執行,須要用next
 3 
 4 def cloth_g(num):
 5     for i in range(num):
 6         yield 'cloth%s'%i
 7 
 8 
 9 g = cloth_g(1000)
10 print(next(g))
11 print(next(g))
12 print(next(g))

 2.4 send關鍵字

 1 # send關鍵字
 2 def func():
 3     print(11111)
 4     ret1 = yield 1
 5     print(22222,'ret1 :',ret1)
 6     ret2 = yield 2
 7     print(33333,'ret2 :',ret2)
 8     yield 3
 9 
10 
11 g = func()
12 ret = next(g)
13 print(ret)
14 print(g.send('alex'))  # 在執行next的過程當中 傳遞一個參數 給生成器函數的內部
15 print(g.send('金老闆'))
16 
17 # 想生成器中傳遞值 有一個激活的過程 第一次必需要用next觸發這個生成器

2.5  預激活生成器 這樣在下面函數執行的時候不用再next了,或者多個函數須要激活的時候,就適合方便用這種方法

 1 # 預激生成器
 2 # def init(func):
 3 #     def inner(*args,**kwargs):
 4 #         ret = func(*args,**kwargs)
 5 #         next(ret)  # 預激活
 6 #         return ret
 7 #     return inner
 8 #
 9 # @init
10 # def average():
11 #     sum_money = 0
12 #     day = 0
13 #     avg = 0
14 #     while True:
15 #         money = yield avg
16 #         sum_money += money
17 #         day += 1
18 #         avg = sum_money/day
19 #
20 # g = average()
21 # print(g.send(200))
22 # print(g.send(300))
23 # print(g.send(600))

2.6 yield from

 1 第一種寫法:
 2 def genrator():
 3     for i in range(5):
 4         yield i
 5     for j in ('hello'):
 6         yield j
 7 g = genrator()
 8 
 9 第二種寫法:
10 
11 def generator_func():
12     yield from range(5)
13     yield from 'hello'
14 g = genrator()

2.7 如何從生產器中取值,三種


# 第一種 :next 隨時均可以中止 最後一次會報錯
# print(next(g))
# print(next(g))
# 第二種 :for循環 從頭至尾遍歷一次 不遇到break、return不會中止
# for i in g:
# print(i)
# 第三種 :list tuple 數據類型的強轉 會把全部的數據都加載到內存裏 很是的浪費內存
# print(g)
# print(list(g))

2.8生成器函數總結

# 一個生成器 只能取一次
# 生成器在不找它要值的時候始終不執行
# 當他執行的時候,要以執行時候的全部變量值爲準
# 主要特徵是 在函數中 含有yield
# 調用一個生成器函數 不會執行這個函數中的帶碼 只是會得到一個生成器(迭代器)
# 只有從生成器中取值的時候,纔會執行函數內部的帶碼,且每獲取一個數據才執行獲得這個數據的帶碼
# 獲取數據的方式包括 next send 循環 數據類型的強制轉化
# yield返回值的簡便方法,若是自己就是循環一個可迭代的,且要把可迭代數據中的每個元素都返回 能夠用yield from
# 使用send的時候,在生成器創造出來以後須要進行預激,這一步可使用裝飾器完成
# 生成器的特色 : 節省內存 惰性運算
# 生成器用來解決 內存問題 和程序功能之間的解耦
三列表推導式和生成器表達式
區別就是中括號和小括號的區別
 1 ##列表推導式
 2 
 3 # print([i**2 for i in range(5)])
 4 #
 5 # l = [1,2,3,-5,6,20,-7]
 6 # print([abs(i) for i in l ])
 7 # print([i for i in l if i%2==1])
 8 ##被30整除數的平方
 9 # print([i**2 for i in range(30) if i%3 ==0])
10 列表推導式
11 [i**2 for i in range(30) if i%3 ==0]
12 
13 生成器表達式
14 g = (i**2 for i in range(30) if i%3 ==0)
相關文章
相關標籤/搜索