Python 基礎之生成器

一.生成器表達式

生成器本質是迭代器,容許自定義邏輯的迭代器
迭代器和生成器區別:
迭代器自己是系統內置的,重寫不了.而生成器是用戶自定義的,能夠重寫迭代邏輯
生成器能夠用來鍾方式建立:
    (1)生成器表達式(裏面是推導式 外面是圓括號)
    (2)生成器函數 (def定義,裏面含有yield)

#(1) 生成器表達式 generator
#[1,2,3,4] => [4,8,12,16]
#i<< 2 i乘以2的2次冪
gen = (i<<2 for i in range(1,5))
print(gen)
from collections import Iterable,Iterator
print(isinstance(gen,Iterator))

##(1)使用next進行調用生成器
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen )
print(res)
res = next(gen)
print(res)
#res = next(gen )  #StopIteration
#print(res)        #越界
##(2)使用for循環調用生成器
gen  = (i<<2 for i in range(1,5))
for i in gen:
    print(i)
##(3)for next 搭配調用生成器
gen = (i<<2 for i in range(1,5))
for i in range(2):
    res = next(gen)
    print(res)函數

 

二.生成器函數

(def定義,裏面含有yield)
#yield相似於return
共同點在於: 執行到這句話都會把值返回出去
不一樣點在於: yield每次返回時,會記住上次離開時執行的位置,下次在調用生成器,會從上次執行的位置往下走
    return 直接終止函數,每次重頭調用
yield 6  yield(6)  2中寫法均可以  yield 6 更像 return 6  的寫法 推薦使用

from collections import Iterator,Iterable
#(1)基本使用
'''若是函數當中包含了yield,那麼這個函數是生成器函數'''
def mygen():
    print("one")
    yield 1
    print("two")
    yield 2
    print("three")
    yield 3

#初始化生成器函數 => 返回一個生成器對象,簡稱生成器
gen = mygen()
print(isinstance(gen,Iterator))
#調用生成器
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)
#res = next(gen)
#print(res)

#代碼解析:
首先初始化生成器函數 返回生成器對象 簡稱生成器
經過next進行調用
第一次調用時候
print(one)
yield 1 記錄當前代碼執行的位置狀態,添加阻塞,暫停在這一行,並返回1,等待下一次調用
第二次調用時候
print(two)
yield 2 記錄當前代碼執行的位置狀態,添加阻塞,暫停在這一行,並返回2,等待下一次調用
第三次調用時候
print(three)
yield 3 記錄當前代碼執行的位置狀態,添加阻塞,暫停在這一行,並返回3,等待下一次調用
第四次調用時候
由於沒有yield返回值了 ,因此直接報錯..
#(2)優化代碼
def mygen2():
    for i in range(1,101):
        yield "個人球衣號%d" %(i)

#初始化生成器 返回生成器對象  簡稱生成器
gen2 = mygen2()

for i in range(50):
    res = next(gen2)
    print(res)


#(3) send 把值發送給一個yield
### send
#next  send 區別:
    next只能取值
    send不但能取值,還能發送值
#send注意點
    第一個 send 不能給 yield 傳值 默認只寫None
    最後一個yield 接受不到send 的發送值
#:
def mygen():
    print("start")
    res = yield 1
    print(res)

    res = yield 2
    print(res)

    res = yield 3
    print(res)

    print("end")

#初始化生成器函數 返回生成器
send 在一次調用的時候,必須給參數None  gen send(None)
是一個硬性要求的語法(由於第一次調用的時候,沒有遇到一個yield)

gen = mygen()
res = gen.send(None)
print(res)
res = gen.send(111)
print(res)
res = gen.send(222)
print(res)
# res = gen.send(333)
# # print(res)

#代碼解析:
第一個調用時,必須使用gen.send(None)
print(start)
res = yield 1記錄當前代碼執行的位置狀態,添加阻塞並返回1,等待下一次調用
第二次調用時,
send先發送,再返回,發送yield 1 res 接收到了111這個值
print(111)
res = yield 2 記錄當前代碼執行的位置狀態,添加阻塞並返回2 ,等待下一次調用
第三次調用時,
send先發送,再返回,發送yield  2 res接收到222這個值
print(222)
res = yield 3 記錄當前代碼執行的位置狀態 添加阻塞並返回3 ,等待下一次調用
第四次調用時,
由於沒有yield繼續返回了,直接報錯,越界錯誤
若是仍然想要執行後面沒有走完的代碼,好比95 96 ,那麼要經過try ...except 異常處理來解決優化

#異常處理格式:
try :
    lst = [1,2]
    print(lst[99])
execpt:
    pass

### yield from :將一個可迭代對象變成一個迭代器返回spa

#:
def mygen():

    #yield ["陳桂濤","五金玲","張俊林"]
    yield from ["陳桂濤","五金玲","張俊林"]

#初始化 一個生成器mygen 返回生成器
gen = mygen()
res = next(gen)
print(res)
res = next(gen)
print(res)
res = next(gen)
print(res)

#用生成器寫斐波那契數列對象

#:
# 1 1 2 3 5 8 13 21 ...
def mygen(n):
    a = 0
    b = 1
    i = 0
    while i< n:
        #print(b)
        yield b
        a,b = b,a+b
        i+=1
gen = mygen(10000)
for i in range(20):
    res = next(gen)
    print(res)three

相關文章
相關標籤/搜索