生成器

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方法調用纔會執行
相關文章
相關標籤/搜索