python中的yield關鍵字的用法詳情

2021-08-28 18:24:57 字數 2898 閱讀 6790

閱讀別人的python原始碼時碰到了這個yield這個關鍵字,各種搜尋終於搞懂了,在此做一下總結:

通常的for…in…迴圈中,in後面是乙個陣列,這個陣列就是乙個可迭代物件,類似的還有鍊錶,字串,檔案。它可以是mylist

= [1, 2, 3],也可以是mylist = [x*x for x in range(3)]。 它的缺陷是所有資料都在記憶體中,如果有海量資料的話將會非常耗記憶體。

生成器是可以迭代的,但只可以讀取它一次。因為用的時候才生成。比如 mygenerator = (x*x for x in

range(3)),注意這裡用到了(),它就不是陣列,而上面的例子是。

我理解的生成器(generator)能夠迭代的關鍵是它有乙個next()方法,工作原理就是通過重複呼叫next()方法,直到捕獲乙個異常。可以用上面的mygenerator測試。

帶有 yield 的函式不再是乙個普通函式,而是乙個生成器generator,可用於迭代,工作原理同上。

簡要理解:yield就是 return 返回乙個值,並且記住這個返回的位置,下次迭代就從這個位置後開始。

帶有yield的函式不僅僅只用於for迴圈中,而且可用於某個函式的引數,只要這個函式的引數允許迭代引數。比如array.extend函式,它的原型是array.extend(iterable)。

send(msg)與next()的區別在於send可以傳遞引數給yield表示式,這時傳遞的引數會作為yield表示式的值,而yield的引數是返回給呼叫者的值。——換句話說,就是send可以強行修改上乙個yield表示式值。比如函式中有乙個yield賦值,a

= yield 5,第一次迭代到這裡會返回5,a還沒有賦值。第二次迭代時,使用.send(10),那麼,就是強行修改yield 5表示式的值為10,本來是5的,那麼a=10

send(msg)與next()都有返回值,它們的返回值是當前迭代遇到yield時,yield後面表示式的值,其實就是當前迭代中yield後面的引數。

第一次呼叫時必須先next()或send(none),否則會報錯,send後之所以為none是因為這時候沒有上乙個yield(根據第8條)。可以認為,next()等同於send(none)。

#encoding:utf-8  

def yield_test(n):

for i in range(n):

yield call(i)

print("i=",i)

#做一些其它的事情

print("do something.")

print("end.")

def call(i):

return i*2

#使用for迴圈

for i in yield_test(5):

print(i,",")

結果是:

>>>   

0 ,

i= 0

2 ,

i= 1

4 ,

i= 2

6 ,

i= 3

8 ,

i= 4

do something.

end.

>>>

def node._get_child_candidates(self, distance, min_dist, max_dist):

if self._leftchild and distance - max_dist < self._median:

yield self._leftchild

if self._rightchild and distance + max_dist >= self._median:

yield self._rightchild

與前面不同的是,這個函式中沒有for迴圈,但它依然可以用於迭代。

node._get_child_candidates函式中有yield,所以它變成了乙個迭代器,可以用於迭代。

執行第一次迭代時(其實就是呼叫next()方法),如果有左節點並且距離滿足要求,會執行第乙個yield,這時會返回self._leftchild並完成第乙個迭代。

執行第二次迭代時,從第乙個yield後面開始,如果有右節點並且距離滿足要求,會執行第二個yield,這時會返回self._rightchild並完成第乙個迭代。

執行第三次迭代時,第二個yield後再無**,捕獲異常,退出迭代。

呼叫過程:

result, candidates = list(), [self]

while candidates:

node = candidates.pop()

distance = node._get_dist(obj)

if distance <= max_dist and distance >= min_dist:

result.extend(node._values)

candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))

return result

上面的node._get_child_candidates(self, distance, min_dist, max_dist)是放在extend()函式中作為引數的,為什麼可以這麼用,就因為extend函式的引數不僅僅支援array,只要它是乙個迭代器就可以。它的原型是array.extend(iterable)。

send()修改上乙個yield掃完返回值

python中yield關鍵字

mylist是乙個可迭代的物件。當你使用乙個列表生成式來建立乙個列表的時候,就建立了乙個可迭代的物件 mylist x x for x in range 3 for i in mylist print i 01 4在這裡,所有的值都存在記憶體當中,所以並不適合大量資料 def creategener...

解析Python中的yield關鍵字

前言 python中有乙個非常有用的語法叫做生成器,所利用到的關鍵字就是yield。有效利用生成器這個工具可以有效地節約系統資源,避免不必要的記憶體占用。一段 def fun for i in range 20 x yield i print good x if name main a fun a....

解析Python中的yield關鍵字

python中有乙個非常有用的語法叫做生成器,所利用到的關鍵字就是yield。有效利用生成器這個工具可以有效地節約系統資源,避免不必要的記憶體占用。def fun for i in range 20 x yield i print good x if name main a fun a.next x...