yield關(guān)鍵字
用法
普通函數(shù):
>>> def f1(): return 'f1'
>>> f1()
'f1'
帶有yield關(guān)鍵字的函數(shù):
>>> def f2(): yield 'f2'
>>> f2()
<generator object f2 at 0x7f453255e4c0>
>>> next(f2())
'f2'
yield將函數(shù)的返回值變成了迭代器,其相當于獲取函數(shù)運算結(jié)果的入口
next()為python的內(nèi)置函數(shù),用于從迭代器獲取函數(shù)運算結(jié)果
機制
>>> def func():
... i = 0
... while True:
... yield i
... i += 1
...
>>> f = func()
>>> [next(f), next(f), next(f)]
[0, 1, 2]
相當于將函數(shù)“暫妥砘”在yield處励堡,再次調(diào)用next()則執(zhí)行到下一個yield
用法舉例
for...in
>>> def func():
... i = 0
... while i < 3:
... yield i
... i += 1
... raise StopIteration # 該行替換成return或者不寫有同樣的效果
...
>>> for i in func():
... print(i)
...
0
1
2
與range(n)相比省很大內(nèi)存空間
內(nèi)置send()函數(shù)
>>> def func():
... i = 0
... while True:
... i += yield i
...
>>> f = func()
>>> next(f)
0
>>> f.send(5)
5
>>> f.send(5)
10
>>> f.send(5)
15
send(X)調(diào)用將X作為上次執(zhí)行到的yield表達式的值(此處相當于i += X)补憾,并再次執(zhí)行next()叛拷。用于介入迭代過程
注意第一次執(zhí)行next()后函數(shù)停止的位置,此時“+=”運算還未被執(zhí)行:
![image.png-14kB](http://static.zybuluo.com/bearda/gey796z1pw7lx6cu4geei57z/image.png)
image.png-14kB
!!必須執(zhí)行至少一次next()后才能執(zhí)行send()浴鸿,如下:
>>> f.send(5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't send non-None value to a just-started generator
類的_iter() 井氢、_next()方法
除了包含yield的函數(shù),還可以自己定義迭代器對象
內(nèi)置函數(shù)iter(obj)調(diào)用相當于通過執(zhí)行obj對象的_iter()方法獲取迭代器對象
內(nèi)置函數(shù)next(obj)調(diào)用相當于通過執(zhí)行obj對象的_next()方法獲取迭代結(jié)果
>>> class counter:
def __init__(self):
self.i = 0
def __iter__(self):
return self
def __next__(self):
self.i += 1
if self.i <= 3: return self.i
else: raise StopIteration
>>> f = iter(counter())
>>> print([next(f), next(f), next(f)])
[1, 2, 3]