知識點:生成器就是通過封裝的演算法進行邊迴圈邊計算的機制,通過next()方法可以每次取乙個計算的值,也就是yield b 這個b是多少(x = next(generator) 這個x就是取到的b)。x = yield,那麼x 就是用於接收外部發來的值(generator.send(5),那麼x就是5)。
通過列表生成式我們可以取得想要的值,但是如果我們建立了乙個包含了百萬個值的列表,而只要取前面的幾個值,顯然這造成了記憶體和時間的浪費。此時,如果我們能用某種方法來把我們想要的值迴圈計算出來,那麼這無疑解決了上面的問題。這種通過某種演算法進行邊迴圈邊計算的功能,稱作生成器。
建立乙個生成器的方法有
>>> g1 = (x for x in range(5))
>>> next(g1) # 通過 next(g1) 或者 g1.send(none) 或者 g1,__next__() 啟動生成器 (next(g1) == g1.send(none))
0>>> next(g1) # 再通過next(g1) g1.send(none) 就可以取得下乙個值或者 g1.send(5)
1>>> g1.send(4)
2>>> list(g1) # 一次性取出剩下的值
[3, 4]
>>> next(g1)
traceback (most recent call last):
file "", line 1, in
stopiteration
當然,重新建立乙個生成器g1,我們可以直接用for迴圈進行迭代取值
>>> g1 = (x for x in range(5))
>>> for i in g1:
... print(i)
...012
34
def
fib(max):
n, a, b = 0, 0, 1
print('aaa')
while n < max:
print(b)
a, b = b, a + b
n = n + 1
print('a')
>>>fib(6)
aaa112
358a
我們說過生成器儲存的是演算法,如果這個演算法封裝在函式裡,那我們如何將這個函式變成生成器呢? 將yield放在迴圈中就可以實現。yield可以接收外部傳送的值(消費者生產者模式就是利用這個特性),還可以用於生成函式內部迭代的值
(1) yield用於生成函式內部迭代的值
def
fib(max):
n, a, b = 0, 0, 1
print('aaa')
while n < max:
yield b
a, b = b, a + b
n = n + 1
print('a')
>>> g = fib(5)
>>>
for i in g:
... print(i)
...aaa11
235a
函式的生成器也可以用next啟動,取值
>>> g = fib(5)
>>> next(g) # 解析:啟動生成器,程式執行到yield處等待,接下來yield就可以用於接收值(下面會有生產者消費者模式)。以後每次next都會迴圈一次while語句
aaa1
>>> next(g)
1>>> next(g)
2>>> next(g)
3>>> g.send(5)
5
(2)yield可以接收外部傳送的值(生產者消費者模式)
def
consumer
(name):
weikou = 0
while weikou < 10:
egg = yield
print("%s 在吃 egg [%s]" % (name,egg))
weikou += 1
c = consumer('tom')
next(c) # 此處等待接收
c.send(1) # tom 在吃 egg [1]
c.send(2) # tom 在吃 egg [2]
defproducer
(): c1 = consumer("tom")
c2 = consumer("john")
c1.__next__()
c2.send(none)
for i in range(3):
c1.send(i)
c2.send(i)
p = producer()
out-------------
tom 在吃 egg [1]
tom 在吃 egg [2]
tom 在吃 egg [0]
john 在吃 egg [0]
tom 在吃 egg [1]
john 在吃 egg [1]
tom 在吃 egg [2]
john 在吃 egg [2]
通過佇列的生產者消費者模式
上面這段**是最簡單的單執行緒下的並行的例子,也即協程,能同時進行多個任務。例子中就是2個消費者在同時吃包子,如果不用生成器的話,那麼就需要等到乙個人吃完了包子,另乙個人再吃。
用於for迴圈的資料型別有2類。
1.集合資料型別 list,dict,tuple,set,str…
2.generator。包括生成器和帶yield的generator function
只要是可以用for迴圈,那他就是可迭代物件(iterable)。
>>>
from collections import iterable
>>> isinstance(,iterable)
true
>>> isinstance([1,2,3],iterable)
true
>>> isinstance((),iterable)
true
>>> isinstance({},iterable)
true
>>> isinstance((x for x in range(10)),iterable)
true
而像生成器這種還能用next()不斷呼叫取值的就是迭代器。而集合資料型別的就不是迭代器
>>>
from collections import iterator
>>> isinstance(,iterator)
false
>>> isinstance((x for x in range(10)),iterator)
true
如果想把集合資料型別轉為迭代器,可以用iter方法進行轉換
>>> isinstance(iter(),iterator)
true
其實python的for迴圈本質上也是用next()呼叫的。
for i in [1,2,3,4,5]:
print(i)
#等價於
it = iter([1,2,3,4,5])
while
true:
try:
x = next(it)
print(x)
except stopiteration as e:
break
協程定義
1.必須在只有乙個單執行緒裡實現併發
2.修改共享資料不需加鎖
3.使用者程式裡自己儲存多個控制流的上下文棧
4.乙個協程遇到io操作自動切換到其它協程
根據協程定義,上面的寫的生產者消費者模型並不屬於嚴格意義上的協程,因為並沒有進行io操作
Python筆記 迭代器 生成器
1.什麼叫迭代?使用for迴圈遍歷取值的過程,叫做迭代 2.什麼是可迭代物件?能夠使用for遍歷取值的物件,叫可迭代物件 可迭代物件 str list set tuple dict 不可迭代物件 int float class 3.什麼是迭代器?迭代器是乙個可以記住遍歷的位置的物件 迭代器物件從集合...
Python學習筆記 生成器與迭代器
首先從一段 來簡單看下什麼是生成器 生成器與列表不同,生成器不會靜態地在記憶體中建立元素,它有點類似於函式,只輸出結果而不建立結果。想要檢視生成器輸出的所有元素,使用for迴圈 for item in g print item 取前n個元素 for i in range 10 print g.nex...
Python生成器和迭代器學習筆記
有時指上述的函式 一種實現了無引數 next 方法和 iter 方法的物件 例項 python內建的一種類,其繼承自collections.iterable py3.4 實現了 iter 或 getitem 方法的物件 class generatorsampleinclass def iter se...