1. 程式人生 > >【25】Python生成器generator

【25】Python生成器generator

一個 內存 容量 nac exce next() gen top 得到

列表生成式
一個小題目:將裏列表[0,1,2,3]裏面的數值都加1.
方法1:

a=[0,1,2,3]
b=[]
for i in range(len(a)):
    b.append(i+1)
a=b
print(a)

方法2:

a = [1,3,4,6,7,7,8]
for index,i in enumerate(a):
    a[index] +=1
print(a)

方法3:

a=[0,1,2,3,4]
a=map(lambda x:x+1,a)
print(a)
for i in a:
    print(i)

方法4:(列表生成式)

a=[i+1 for i in range(10)]
print(a)

看出了什麽沒有?沒錯,同樣的功能,實現的代碼越來越精簡。

進入正題:生成器
通過列表生成式,我們可以直接創建一個列表。但是,受內存限制,列表的容量肯定有限。如果創建大量數據,結果只用到幾條,那也是相當占用空間的。
所以列表元素按照某種算法推算出來,那我們是否可以在循環的過程中不斷的推算出後續的元素呢?這樣可以節約大量空間。在python中,這種一邊循環一邊計算的機制,成為生存器:generator。
創建生成器有很多種方法,最簡單的方法就是把一個列表[]改成(),就創建了一個generator:

g=(i+1 for i in range(10))
print(g)

運行的結果就是根據算法生成的,只有在循環調用的時候,才會顯示。

l=[x+1 for x in range(10)]
print(l)

列表會顯示所有數據。而生成器generator需要通過循環或者next()函數調用才能算出來。
直到計算到最後一個元素,沒有更多的元素時,會拋出異常StopIteration的錯誤。

下面可以用函數實現:比如,著名的斐波拉契數列(Fibonacci),除第一個和第二個數外,任意一個數都可由前兩個數相加得到:
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
        n=n+1
    return "done"
print(fib(10))

而實現生成器的轉換,只需要修改一步。將print(b),改成yield b即可

def fib(max):
    n,a,b=0,0,1
    while n<max:
        # print(b)
        yield b  ##有yield存在時就不叫函數了,而叫生成器
        a,b=b,a+b
        n=n+1
    return "done"
print(fib(10))
f=fib(10)
g=fib(6)
while True:
    try:
        x=next(g)
        print("g",x)
    except StopIteration as e:  #異常起個名字叫 e
        print("Generator return value:",e.value)
        break
# print(f.__next__())
# print(f.__next__())
# print(f.__next__())
# print(f.__next__())
# print(f.__next__())
# print(f.__next__())
# print(f.__next__())
# print(f.__next__())
# print(f.__next__())
# print(f.__next__())
# print(f.__next__())

生成器並行運行

import time
def consumer(name):
    print("%s eat!"%name)
    while True:
        baozi=yield #yield沒有返回值空的
        print("包子%s來了,被%s吃了"%(baozi,name))

# c=consumer("alex")
# c.__next__()
# b1="韭菜餡"
# b2="肉餡"
# c.send(b1) ##調用b1,同時給傳值
# c.__next__()

#攜程(nginx異步處理)
def producer(name):
    c1=consumer("A")
    c2=consumer("B")
    c1.__next__()
    c2.__next__()
    print("準備包子!!!")
    for i in range(10):
        time.sleep(2)
        print("做一個,兩人分著吃!")
        c1.send(i)
        c2.send(i)
producer("alex")

【25】Python生成器generator