python(可迭代對象,迭代器,生成器及send方法詳解)

一.可迭代對象
對象必須提供一個__iter__()方法,若是有,那麼就是可迭代對象,
像列表,元祖,字典等都是可迭代對象
可以使用isinstance(obj,Iterable)方法判斷
1 from collections import Iterable,Iterator
2 l={'2':2,'fd':5,'f':6}
3 l_i=l.__iter__()
4 
5 print(isinstance(l,Iterable))
6 print(isinstance(l_i,Iterator))

結果:併發

True函數

Truespa

二.迭代器線程

迭代器協議:
對象必須提供一個next方法,執行該方法要麼返回迭代中的下一項,要麼就引發一個StopIteration異常,以終止迭代 (只能日後走不能往前退)
符合迭代器協議的就是迭代器
一個對象是迭代器也是可迭代對象

from collections import Iterable,Iterator
l={'2':2,'fd':5,'f':6}
l_i=l.__iter__()
s=isinstance(l,Iterable)
print(s)
print(isinstance(l_i,Iterator))
打印結果:
True
True
三.生成器
遵循迭代器協議,至關於一種特殊的迭代器對象
1.生成器表達式
(1)三元表達式(必須是三元)
name = '李'
res='兒子' if name == '李' else '爸爸'
print(res)
打印結果:
兒子
(2)列表解析
所謂列表解析就是列表內包含兩元或三元表達式(不能是四元)
1 l=['螞蟻%s' %i for i in range(10)]
2 l1=['螞蟻%s' %i for i in range(10) if i >5]
3 print(l)
4 print(l1)
打印結果:
['螞蟻0', '螞蟻1', '螞蟻2', '螞蟻3', '螞蟻4', '螞蟻5', '螞蟻6', '螞蟻7', '螞蟻8', '螞蟻9']
['螞蟻6', '螞蟻7', '螞蟻8', '螞蟻9']
一行代碼寫出9*9乘法表:
print('\n'.join([' '.join(["%dX%d=%-2d" %(i,m,m*i) for i in range(1,m+1)]) for m in range(1,10)]))
原理:.join()方法處理的結果是一個總體的字符串
(3)生成器表達式
1  l=['螞蟻%s' %i for i in range(10)]#列表
2  l=('螞蟻%s' %i for i in range(10))#生成器表達式
3  和列表相比不佔用內存,使用一次生成一次
4 l=('螞蟻%s' %i for i in range(10))
5 print(l)
6 print(l.__next__())
7 print(l.__next__())
8 print(next(l))
9 print(next(l))
運行結果:
<generator object <genexpr> at 0x000002191AFB5BA0>
螞蟻0
螞蟻1
螞蟻2
螞蟻3

2.生成器函數
優勢:
不會當即執行,節省內存。
有須要時用一個現運行出一個,yield會保留當前狀態,下次從當前位置繼續運行,直到再次碰到yeild。
對比兩個過程理解:
過程一(作出一個賣一個,即調用一次現運行出來一個結果)
1 def product_baozi():
2    for i in range(100):
3       print('正在生產包子%s' %i)
4       yield '一屜包子%s' %i #i=1
5       print('開始賣包子')
6 pro_g=product_baozi()
7 baozi1=pro_g.__next__()
運行結果:
正在生產包子0
過程二:(調用第二次,現運行出來第二個結果)
1 def product_baozi():
2    for i in range(100):
3       print('正在生產包子%s' %i)
4       yield '一屜包子%s' %i #i=1
5       print('開始賣包子')
6 pro_g=product_baozi()
7 
8 baozi1=pro_g.__next__()
9 baozi1=pro_g.__next__()
打印結果:
正在生產包子0
開始賣包子
正在生產包子1
3.生成器特性
特性一:for循環能夠遍歷生成器
def eges():
for i in range(5):
yield '雞蛋%s' %i #i=1
pro_g=eges()

for i in pro_g:
print(i)
特性二:生成器只能迭代一次,用完就沒了
1 with open('人口普查','r',encoding='utf-8') as f:
2     def g_population():
3       for i in f:
4          yield i
5 
6 
7 print(sum(eval(l)['population']  for l in g_population()))
8 print(g_population().__next__())  #此句會拋出異常
4.利用生成器實現單線程併發
send()方法,
有一個參數,該參數指定的是上一次被掛起的yield語句的返回值,
而且再次遇到yeild會向send傳回一個值。
實例:飯店吃飯
 1 import time
 2 def consetomer():
 3     print('服務員點餐')
 4     time.sleep(5)
 5     for i in range(5):
 6          cai=yield i   #接受send的傳值,並向下執行,直到結束或遇到下一個yield(此時的yield會向send傳回一個值)
 7          print('顧客開始吃第%s個菜' %cai)
 8 
 9 def canting():
10     g1=consetomer()
11     print(g1.__next__())
12     print('廚師準備作菜')
13     for i in range(1,5):
14         time.sleep(1)
15         print('第%s個菜作好了' %i)
16         print('第%s個好吃' %g1.send(i)) #傳送上一次掛起的yield並等待接受下一次yeild返回值
17 canting()
 

 

 

打印結果:code

 1 服務員點餐
 2 0
 3 廚師準備作菜
 4 第1個菜作好了
 5 顧客開始吃第1個菜
 6 第1個好吃
 7 第2個菜作好了
 8 顧客開始吃第2個菜
 9 第2個好吃
10 第3個菜作好了
11 顧客開始吃第3個菜
12 第3個好吃
13 第4個菜作好了
14 顧客開始吃第4個菜
15 第4個好吃
相關文章
相關標籤/搜索