1.列表生成式
經過列表生成式,能夠直接建立一個列表,可是受內存限制,列表容量有限,並且建立的列表太大,佔用存儲空間
a = [i*2 for i in range(10)] print(a) #[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
2.生成器
定義:經過某種算法將列表推算出來,不用建立完整的list,節省大量內存空間,這種一邊循環一邊計算的機制,稱做生成器,generator
特色:只有在調用的時候才產生數據,不會象列表同樣先將全部數據加載到內存;只記錄當前位置,不會象列表同樣記錄全部數據下標;只有一個方法__next__
2.1將列表生成式轉化爲生成器
b = (i*2 for i in range(10)) #將一個列表生成式轉化生成器只須要將[]-->() print(b) #<generator object <genexpr> at 0x00492870> for i in b: #經過循環調用生成器中數據 print(i) if i > 5: #若是在循環中終斷程序,會接着調用生成器中的數據 break print(b.__next__()) print(b.__next__()) #經過__next 方法一個個調用生成器中數據 print(b.__next__()) print(b.__next__()) print(b.__next__())
2.2經過函數實現生成器python
斐波那契數列:除第一個和第二個數以外,任意一個數均可以由前兩個數相加獲得:
1,1,2,3,5,8,13,21,34...........
用函數實現斐波那契數列以下:
def fib(max): n,a,b = 0,0,1 while n < max: print(b) a,b = b,a+b #注:a,b = b,a+b 至關於t = (b,a+b) a=t[0] b=t[1] n = n + 1 return "done" fib(10)
將上面函數變成生成器,只要把函數中的print(b)改爲yeild 便可:
def fib(max): n,a,b = 0,0,1 while n < max: #print(b) yield b #當程序執行到yield會中斷,直到下次調用接着執行 a,b = b,a+b #注:a,b = b,a+b 至關於t = (b,a+b) a=t[0] b=t[1] n = n + 1 return "--done--" print(fib(10)) <generator object fib at 0x00572870>
生成器調用:算法
f = fib(10) for i in f: #使用for循環調用生成器數據 print(i) print(f.__next__()) #使用__next__調用 print(f.__next__()) #因爲生成器會記錄當前位置,這個時候中止生成器去幹別的,下次會接着執行 print("----------------") print(f.__next__()) print("-----------------")
使用__next__方法調用生成器數據超過指定的範圍出現報錯,報錯信息:StopIteration: --done--
可使用如下方法執行該生成器,將這個報錯信息抓出正常返回:
while True: try: x = f.__next__() print("f:",x) except StopIteration as e: print("generator return value",e.value) break
3.生成器實現單線程下的並行效果,生產者消費者模型ide
import time def consumer(name): print("%s 開始準備吃包子"%(name)) while True: baozi = yield #每調用一次生成器,每次在執行到yield的時候會跳出,直到下次調用接着執行 print("包子%s來了,被%s吃了"%(baozi,name)) def produer(name): c1 = consumer("A") #consumer是生成器,將其賦值給c1,c2 當用__next__方法調用時,c1和c2分別執行到yield跳出繼續執行produer函數 c2 = consumer("B") c1.__next__() #執行consumer這個生成器,當執行到yield時中斷跳出 c2.__next__() #執行consumer這個生成器,當執行到yield時中斷跳出 print("開始作包子了") for i in range(10): time.sleep(1) c1.send(i) #__next__只是在調用yield,而send在調用的同時還會給yield傳值 c2.send(i) # produer("cx") #注:若是是函數直接consumer("A") 就會執行,但有yield以後就變成生成器,必須使用循環,或者next方法調用纔會執行