一、生成器
生成器指的是生成器物件,可由生成器表示式得到,也可使用 yield 關鍵字得到乙個生成器函式,呼叫這個函式得到乙個生成器物件
生成器物件,是乙個可迭代物件,是乙個迭代器
生成器物件,是延遲計算、惰性求值的
1.1 生成器函式
函式體重包含 yield 語句的函式,就是生成器函式,呼叫後返回生成器物件
m = (i for i in range(5)) # 生成器表示式
print(type(m))
print(next(m))
print(next(m))
def inc(): # 生成器函式
for i in range(5):
yield i
print(type(inc))
print(type(inc()))
g = inc()
print(type(g))
print(next(g))
for x in g:
print(x)
print('!!!!!!!!!!!!!!!!!!!!!!')
for y in g:
print(y)
普通函式呼叫,函式會立即執行直到執行完畢
生成器函式呼叫,並不會立即執行函式體,而是需要使用 next 函式來驅動生成器函式執行後獲得的生成器物件
生成器表示式和生成器函式都可得到生成器物件,只不過生成器函式可寫的更加複雜的邏輯
二、生成器的執行
def gen():
print('line 1')
yield 1
print('line 2')
yield 2
print('line 3')
return 3
yield 4
next(gen()) # line 1
next(gen()) # line 1
g = gen()
print(next(g)) # line 1
print(next(g)) # line 2
print(next(g)) # stopiteration
print(next(g), 'end')) # 沒有元素給個預設值
在生成器函式中,可多次 yield,每執行一次 yield 後會暫停執行,把 yield 表示式的值返回
再次執行會執行到下乙個 yield 語句又會暫停執行
return 語句依然可以終止函式執行,但 return 語句的返回值不能被獲取到
return 會導致當前函式返回,無法繼續執行,也無法繼續獲取下乙個值,丟擲 stopiteration 異常
若函式沒有顯式的 return 語句,若生成器函式執行到結尾(相當於執行了 return none),一樣會丟擲 stopiteration 異常
2.1 生成器函式
包含 yield 語句的生成器函式呼叫後,生成 生成器物件 的時候,生成器函式的函式體不會立即執行
next(generator) 會從函式的當前位置向後執行到之後碰到的第乙個 yield 語句,會彈出值,並暫停函式執行
再次呼叫 next 函式,和上一條一樣的處理過程
繼續呼叫 next 函式,生成器函式若結束執行了(顯式或隱式呼叫了 return 語句),會丟擲 stopiteration 異常
三、生成器應用
3.1 無限迴圈
def counter():
i = 0
while true:
i += 1
yield i
c = counter()
print(next(c))
print(next(c))
print(next(c))
3.2 計數器
def inc():
def counter():
i = 0
while true:
i += 1
yield i
c = counter()
return next(c)
print(inc())
print(inc())
print(inc())
修改上例
def inc():
def counter():
i = 0
while true:
i += 1
yield i
c = counter()
def inner():
return next(c)
return inner # return lambda : next(c)
foo = inc()
print(foo())
print(foo())
print(foo())
**中的 inner 函式可由 lambda 表示式代替
3.3 斐波那契數列
def fib():
x = 0
y = 1
while true:
yield y
x, y = y, x + y
foo = fib()
for i in range(101):
print(next(foo))
3.4 生成器互動
python 提供了乙個和生成器物件互動的方法 send,該方法可以和生成器溝通
# 重置功能的計數器
def inc():
def counter():
i = 0
while true:
i += 1
response = yield i
if response is not none:
i = response
c = counter()
return lambda x=false: next(c) if not x else c.send(0)
foo = inc()
print(foo())
print(foo())
print(foo())
print(foo(true))
print(foo())
print(foo())
print(foo())
呼叫 send 方法,就可把 send 的實參傳給 yield 語句做結果,這個結果可在等式右邊被賦值給其它變數
send 和 next 一樣可推動生成器啟動並執行
3.5 協程 coroutine
生成器的高階用法
它比程序、執行緒輕量級,是在使用者空間排程函式的一種實現
python 3 asyncio 就是協程實現,已經加入到標準庫
python 3.5 使用 async、await 關鍵字直接遠端支援協程
協程排程器實現思路
有兩個生成器 a、b
next(a) 後,a 執行到了 yield 語句暫停,然後去執行 next(b),b 執行到 yield 語句也暫停,然後再次呼叫 next(a),再呼叫 next(b),周而復始,就實現了排程效果
可引入排程的策略來實現切換的方式
協程是一種非搶占式排程
四、yield from 語法
從 python 3.3 開始增加了 yield from 語法,使得 yield from iterable 等價於 for item in iterable: yield item
yield from 就是一種簡化語法的語法糖
def inc():
for x in range(1000):
yield x
# 使用 yield from 簡化
def inc():
yield from range(1000)
foo = inc()
print(next(foo))
print(next(foo))
print(next(foo))
本質上 yield from 的意思就是從 from 後面的可迭代物件中拿元素乙個個 yield 出去
python 生成器函式
python 函式的定義體中有 yield 關鍵字,該函式就是生成器函式。呼叫生成器函式時,會返回乙個生成器物件。生成器函式的定義體執行完畢後,生成器物件會丟擲stopiteration 異常。def gen a print start yield 1 print starting yield 2 ...
python函式 生成器
1.生成器 是乙個特殊的迭代器 迭代的抽象層級更高 所以,擁有迭代器的特性,惰性計算資料,節省記憶體。能夠記錄下狀態,並通過next 函式,訪問下乙個狀態。具備可迭代性。但是,如果打造乙個自己的迭代器,比較複雜,需要實現很多方法 在後續的面相物件程式設計中會講解 所以,就有乙個更加優雅的方式 生成器...
Python 生成器函式
生成器函式 包含yield語句的函式 生成器物件 生成器物件和迭代器物件行為相似,都支援可迭代介面 next 若想執行生成器函式內部語句,則需要迭代協議 a 生成器函式被呼叫時,並不會執行函式內部語句,而是返回乙個生成器物件 b 每執行一條語句,返回對應的乙個yield數值,雖然函式被yield臨時...