Python yield的理解與簡單測試

2021-08-07 02:53:45 字數 3282 閱讀 3186

在學習非同步io,會涉及到協程,最簡單的協程,可以用yield來模擬,最初學習yield的時候就沒搞太明白,今天看了些部落格,終於搞得懂了。

下面給出乙個作者的總結的知識點,讓我理解了。謝謝

主要的掌握

1.通常的for...in...迴圈中,in後面是乙個陣列,這個陣列就是乙個可迭代物件,類似的還有鍊錶,字串,檔案。它可以是mylist = [1, 2, 3],也可以是mylist = [x*x for x in range(3)]。

它的缺陷是所有資料都在記憶體中,如果有海量資料的話將會非常耗記憶體。

2.生成器是可以迭代的,但只可以讀取它一次。因為用的時候才生成。比如 mygenerator = (x*x for x in range(3)),注意這裡用到了(),它就不是陣列,而上面的例子是。

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

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

5.yield 是乙個類似 return 的關鍵字,迭代一次遇到yield時就返回yield後面的值。重點是:下一次迭代時,從上一次迭代遇到的yield後面的**開始執行。

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

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

8.send(msg)與next()的區別在於send可以傳遞引數給yield表示式,這時傳遞的引數會作為yield表示式的值(這裡應該理解到yield表示式,它是乙個表示式,而不僅僅yield產生乙個值),而yield的引數是返回給呼叫者的值。——換句話說,就是send可以強行修改上乙個yield表示式值。比如函式中有乙個yield賦值,a = yield 5,第一次迭代到這裡會返回5,a還沒有賦值。第二次迭代時,使用.send(10),那麼,就是強行修改yield 5表示式的值為10,本來是5的,那麼a=10

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

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

#encoding:utf-8

def gener():

print "1"

x=yield "hello"

print "2","x=",x

y=5+(yield x)

print "3","y=",y

g=gener()

print g.next()#g.send(none)

'''這裡第一次呼叫時的兩種方法

輸出:1

hello #程式到yield就結束,下次呼叫時從斷開處繼續(這個特點會用在協程,非同步io,併發技術中)

'''print g.send(5)

'''繼上一次斷處執行print "2","x=",x y=5+(yield x)

由於send(5),那麼上一次yield表示式的值就位5,所以x=5

然後執行到yield x,則輸出yield後面的引數5

'''print g.send(2)

'''此時send(2),則上一次yield的表示式的值為2

則y=7

'''

二、使用yield實現協程

#coding=utf-8

__author__ = "zhangxiaozi"

#!/usr/bin/python

def consumer():

r = ''

while true:

n = yield r 

#消費者通過yield表示式拿到訊息,再把yield的引數當做反饋結果反饋給生產者

if not n:

print("not n...")

return

print('[consumer] consuming %s...' % n)

r = '200 ok'

def produce(c):

f = c.send(none)  #第一次f等於''

print('[producer] consumer first return: %s' % f)

n = 0

while n < 2:

n = n + 1

print('[producer] producing %s...' % n)

# 一旦產生東西就通過r = c.send(n)切換到消費者consumer執行

r = c.send(n)

print('[producer] consumer return: %s' % r)

c.close()

c = consumer()

produce(c)

程式結果:

[producer] consumer first return:

[producer] producing 1...

[consumer] consuming 1...

[producer] consumer return: 200 ok

[producer] producing 2...

[consumer] consuming 2...

[producer] consumer return: 200 ok

協程的說明:

注意到consumer函式是乙個generator,把乙個consumer傳入produce後:

首先呼叫c.send(none)啟動生成器;

然後,一旦生產了東西,通過c.send(n)切換到consumer執行;

consumer通過yield拿到訊息,處理,又通過yield把結果傳回;

produce拿到consumer處理的結果,繼續生產下一條訊息;

produce決定不生產了,通過c.close()關閉consumer,整個過程結束。

整個流程無鎖,由乙個執行緒執行,produce和consumer協作完成任務,所以稱為「協程」,而非執行緒的搶占式多工。

python yield 簡單理解

要想理解yield的概念,我們必須理解python中迭代器和生成器的概念與作用。1.迭代器 iterables python中可以直接作用於for迴圈的物件,比如 列表 元祖 字典 集合 字串等統稱為可迭代物件。迭代器是乙個實現了迭代器協議的物件,其可以呼叫next 方法得到下乙個結果,在結果末尾呼...

Python yield 與 send 實現協程

我們來看看在函式內部含有yield語句達到的效果。首先,我們來看看以下 def foo while true x yield print value x g foo g是乙個生成器 next g 程式執行到yield就停住了,等待下乙個next g.send 1 我們給yield傳送值1,然後這個值...

Python yield 的使用方法

帶有 yield 的函式在 python 中被稱之為 generator 生成器 使用 yield 可以大大簡化 yield 返回的是乙個generator物件,帶有 yield 的函式不再是乙個普通函式 def fab max n,a,b 0,0,1 while n fab 5 yield 的作用...