yield基礎用法
阿新 • • 發佈:2020-07-27
yield 是產出的意思,就是返回一個值,這一點有點像return,但是不會結束函式的執行。那它什麼時候繼續執行呢?等待下一次迭代器被呼叫時候返回上次中斷的地方,
利用這個特性可以實現range函式:
def my_range(max_num):
i = 0
while i < max_num:
yield i # 從此出產出i,下次呼叫時,從這裡繼續
i = i + 1
for v in my_range(10): # 帶有yield 的函式呼叫後是個生成器物件,可迭代的
print(v)
輸出:
0 1 2 3 4 5 6 7 8 9
使用內建next
方法可以呼叫生成器,可以執行到下一個yield,還可以使用生成器自帶的send方法呼叫它,並且還可以往函式內部傳值:
def f1():
i = 0
while 1:
x = yield i
print(f"x is {x}")
gen = f1()
next(gen) # 預啟用生成器
gen.send('hh') # 傳送的字串賦值給了 f1函式中的x,也就是yield的賦值語句
輸出:
x is hh
貌似沒啥用,可以用這個寫一個計算平均值的程式,每次使用send傳送給生成器一個數字,生成器返回所有數字的平均值:
def average():
count = 0
total = 0
ave = None
while 1:
new_num = yield ave
count = count + 1
total = total + new_num
ave = total / count
gen = average()
gen.send(None)
print(gen.send(1))
print(gen.send(2))
print(gen.send(3))
輸出:
1.0
1.5
2.0
用一個yield 呼叫另外一個yiled會返回什麼呢?
def f1():
yield 100
def f2():
yield f1()
if __name__ == '__main__':
gen = f2()
print(next(gen))
輸出:
<generator object f1 at 0x10a855650>
輸出f1的生成器,呼叫完f1() ,生成一個生成器然後在f2裡面被yield出去了,那能不能獲取f1生成器中的內容yield出去?可能要這麼寫:
def f1():
yield 100
def f2():
yield next(f1())
if __name__ == '__main__':
gen = f2()
print(next(gen))
輸出:
100
它還提供了一種專用的方法, yield from
:
def f1():
yield 100
def f2():
yield from f1()
if __name__ == '__main__':
gen = f2()
print(next(gen))
yield from
可以yield別的生成器的內容,有人把 帶yield from
的生成器叫委託生成器,真正的生成器叫子生成器,而且還可以通過委託生成器呼叫子生成器:
def f1():
x = yield 100
print(f"x is {x}")
def f2():
yield from f1()
if __name__ == '__main__':
gen = f2()
print(next(gen))
gen.send('hhh') # 實際上傳送給 f1的生成器了
輸出:
Traceback (most recent call last):
File "/Users/wuhf/PycharmProjects/cookdata/cookdata/web/test/run_yield6.py", line 13, in <module>
gen.send('hhh')
StopIteration
100
x is hhh