python 迭代器和生成器 學習

##列表生成式  能靈活的生成所需列表
temp_list=[i*2 for  i in range(1,11)]
#print(temp_list)

##上面的列表生成式,就是使代碼更簡潔
a=[]
for i in range(1,11):
    a.append(i)
#print(a)

###迭代器&生成器
'''
經過列表生成式,建立一個列表時,當數據量較大時,不只佔用不少的存儲空間,若是咱們僅須要訪問幾個元素,那其餘空間就白白浪費了。
若是能夠按指定算法推算出要訪問的元素,即便用時,纔開闢空間,這種一邊循環一邊計算的機制,稱爲‘生成器’ generator
'''
#一、用列表做爲生成器
temp_list=[i*2 for  i in range(1,11)]
#print(temp_list)                        #已經準備好了每一個元素 [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
temp_gen=(i*2 for  i in range(1,11))
#print(temp_gen)
#  運行結果<generator object <genexpr> at 0x03593570>,沒有準備每一個元素,須要經過_next_()
#因此生成器不能像list同樣,使用切片的方式訪問
for i in temp_gen:
    #print(i)
    pass
#在建立一個生成器後,基本上不會調用_next_()訪問,而是經過for循環來迭代它,且不關心stopIteration的錯誤。
# 二、用函數來指定生成器的規則
# 我寫的斐波拉契數列:除第一個和第二個數外,任意一個數均可由前兩個數相加獲得
i=1
bef=0
fibo=[]
while i<20:
    if len(fibo)<2:
        fibo.append(i)
        bef = i
    else:
        bef=fibo[-2]+bef
        fibo.append(bef)
    i=i+1
#print(fibo)
#大神寫的 [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print(b)
        a, b = b, a + b
        n = n + 1
    return 'done'
#print(fib(20))

''' 這裏賦值以前,先計算右邊的值,因此賦值前a=1,b=2 ,計算完後a,b=(2,1+2) 因此a=2 b=3
>>> a,b=1,2
>>> t=(b,a+b)
>>> t[0]
2
>>> t[1]
3
>>> a,b=(b,a+b)
>>> a
2
>>> b
3
'''
#要想該函數做爲生成器,將print(b) 修改成yield b
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'
print(fib(20)) #運行結果<generator object fib at 0x00AF37B0>  
#函數加yield後,再也不是函數了,是生成器了,return的值,在捕獲異常時使用,以下:

#死循環一直調用next,會超出生成器的範圍
#while True:
#    print(g.__next__()) #StopIteration: done 拋出異常了,捕獲它

while True:
    try:
        print(g.__next__())
    except    StopIteration as e:
        print('Generator return value:',e.value)
        break                                                                                                                                                                                                                                            
#函數使用yield,當訪問生成器g時,去執行函數fib(),執行到yield時,函數就暫停,再次調用fib()函數時,又接着執行yield後面的,並執行到yield的位置
#即yield一個值後,函數暫停,再次訪問生成器時,再規則生產規則yield一個值。
#調用fib(),保存了中斷前的狀態。

使用生成器,在單線程設備中實現‘多線程’運行算法

#實現串行
#定義生成器
def get_generator():
    for seed in range(1,11):
        yield  seed;
#使用生成器的數據
def worker(seed):
    return seed*seed
#for i in get_generator():#實現了串行任務,我一個數據你使用了,我再產生一個數據你才能使用
#    print(worker(i))
#進一步,可將其抽象爲下面的函數:
def serial_yield(generator,worker):
    for seed in generator():
        yield  worker(seed)  #又申明一個生成器

做業,寫一個包包子的任務,包10個包子,把任務分紅幾塊,分工串行(分擀麪皮、包包子,包完一個計算一個。)使用生成器,實現並行多線程

 

def  ganmianpi():
    while True:
        yield  '麪皮擀好啦,接着!'
def baobaozi():
    n=1
    while n<11:
        print(ganmianpi().__next__())
        yield  '包完第%s個包子'%n
        n=n+1
for baozi in baobaozi():
    print(baozi)

用生成器實現並行(協調式)app

import  time
def consumer(name):
    print('%s 準備吃包子啦!'%name)
    while True:
        baozi=yield

        print('包子<%s>來了,被<%s>吃了! '%(baozi,name))
def producter(name):
    c=consumer(name)#這裏是申明變量c ,是生成器,不是執行函數,調試時不會進入迭代器內部
    c.__next__()#訪問生成器的元素,纔會去迭代器內部看生成規則
    print('老子開始準備包包子啦!')

    for i in range(1,6):
        time.sleep(1)
        print('作了%s個包子!'%i)
        c.send(i)

producter('weii')#這裏是調用函數哦

 上面的任務其實仍是串行的,只是看到多個不一樣的任務在同時進行,任務在不一樣的交替,看起來像並行。函數

 直接調用consumer該生成器,yield無對應值,返回爲None,那這樣給yield傳值呢spa

c=consumer('Chenweiei')
c.__next__()
c.__next__() #_next_必需要加() 才能訪問到元素
'''Chenweiei 準備吃包子啦!
包子<None>來了,被<Chenweiei>吃了! 
'''
c.send('白菜餡的') #喚醒當前的生成器,並賦值給yield,繼續往下走,c.__next__() 是隻喚醒
'''Chenweiei 準備吃包子啦!
包子<白菜餡的>來了,被<Chenweiei>吃了! 
'''
from collections import  Iterator
print(isinstance([],Iterator)) #False 判斷對象是否爲迭代器
print(isinstance(c,Iterator)) #True--------------------------------
#可迭代對象(可循環的對象) charpter【13】
#迭代器:可用next()函數調用,並不斷返回下一個值的對象,在可迭代對象上又加了條件

從上面截圖,能夠看到列表就沒有next() 函數線程

相關文章
相關標籤/搜索