##列表生成式 能靈活的生成所需列表 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() 函數線程