1. 程式人生 > >Python學習---生成器的學習1210

Python學習---生成器的學習1210

fun 釋放 不同 語句 理解 再次 而是 普通 之前

在Python中,這種一邊循環一邊計算的機制,稱為生成器:

結論: 生成器本質是一個函數,不同於函數的是它生成的是一個對象,不執行函數內的代碼

1.1. 列表生成器

列表生成器: 列表是直接生成數字在內存,可以隨時調用

元組顯示的類型是生成器,只存儲在內存中,但是只有在調用的時候生成

b = [x for x in range(10)]
c = (x for x in range(10))
print(b, c)
print(type(b), type(c))

技術分享圖片

生成器的創建方法

1. c = (x for x in range(10)), 利用 ()來生成

2. 利用yield()方法

利用()生成

c = (x for x in range(10))
# print(c.next)  在Py2中的方法
print(c.__next__())  # 輸出0,__next__()是一個私有方法,不建議用
print(next(c))       # 輸出1, 利用next內置函數叠代輸出,當輸出到最有一個元素的時候,就不會輸出數據
for i in c:          # for調用C裏面的next去叠代輸出,節約內存空間
    print(i, end=‘\t‘)  # 2 3 4 5 6 7 8 9 ,因為前面輸出了0,1,所以指針指向了下一位,所以從2開始

利用yield創建:

如果一個函數定義中包含yield關鍵字,那麽這個函數就不再是一個普通函數,而是一個generator

最難理解的就是generator和函數的執行流程不一樣。函數是順序執行,遇到return語句或者最後一行函數語句就返回。而變成generator的函數,在每次調用next()的時候執行,遇到yield語句返回,再次執行時從上次返回的yield語句處繼續執行。

def fun():
    print(‘ok‘)
    yield 1  # 有yield關鍵字,代表fun()非函數,是一個生成器
    # 此時作為return 直接結束了函數


g = fun() # 此時的fun()是一個生成器對象,而非函數
print(g)  # <generator object fun at 0x0000000000AFDEB8>
a = next(g)
print(‘a‘, a) # 接收了傳遞回來的值1
# next(g)     # ok, 當遇到yield1的時候,可以認為是return 1,結束了函數的執行,g釋放,所以後面的print在執行會報錯
print(next(g))  # print()裏面是一個可叠代對象,yield 1返回一個1被print捕捉到,所以 叠代輸出 ok 和 1

生成器的send()方法:使用之前必須先進入到生成器裏面,然後利用send()賦值給上次返回處

def fun():
    print(‘ok1‘)
    count = yield 1
    print(count)
    yield 2

b = fun()
b.send(None)  # 等價於 next(b),開始進入到函數, 直到遇到了yield 1後返回到此處,執行後面的b.send(‘hello world‘)
tt = b.send(‘hello world‘)  # 進入到退出的yield 1的位置,將‘hello world‘賦值給count進行打印,遇到yield 2後返回結果到此處
print(tt)     # 將yield 2的結果賦給tt, 然後進行打印

技術分享圖片

生成器的應用

還可通過yield實現在單線程的情況下實現並發運算的效果

import time
def consumer(name):
    print("%s 準備吃包子啦!" %name)
    while True:
       baozi = yield
       print("包子[%s]來了,被[%s]吃了!" %(baozi,name))
def producer(name):
    c = consumer(‘A‘)
    c2 = consumer(‘B‘)
    c.__next__()
    c2.__next__()
    print("老子開始準備做包子啦!")
    for i in range(10):
        time.sleep(1)
        print("做了2個包子!")
        c.send(i)
        c2.send(i)
producer("ftl1012")

利用生成器實現斐波那契

def fib(max):
    n, b, a = 0, 0, 1
    while n <= max:
        # print(b, end=‘\t‘)
        yield b  # 等價於 print(b),將我們需要的結果先存放起來
        b, a = a, b+a  # 賦值是同時執行的
        n += 1

gen = fib(6)
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))

【學習參考】http://www.cnblogs.com/alex3714/articles/5765046.html

【學習參考】http://www.cnblogs.com/yuanchenqi/articles/5830025.html

Python學習---生成器的學習1210