成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

python中的yield使用詳解

CntChen / 2674人閱讀

摘要:是的一個(gè)關(guān)鍵字,剛接觸的時(shí)候?qū)@個(gè)關(guān)鍵字一知半解,掌握之后才發(fā)現(xiàn)這關(guān)鍵字有大用,本文將對(duì)的使用方法好好梳理一番。使用創(chuàng)建生成器在中,生成器是一種可迭代對(duì)象,但可迭代對(duì)象不一定是生成器。

yield是python的一個(gè)關(guān)鍵字,剛接觸python的時(shí)候?qū)@個(gè)關(guān)鍵字一知半解,掌握之后才發(fā)現(xiàn)這關(guān)鍵字有大用,本文將對(duì)yield的使用方法好好梳理一番。

1 使用yield創(chuàng)建生成器

在python中,生成器是一種可迭代對(duì)象,但可迭代對(duì)象不一定是生成器。
例如,list就是一個(gè)可迭代對(duì)象

>>> a = list(range(3))
>>> for i in a:
    print(i)

0
1
2
3

但是一個(gè)list對(duì)象所有的值都是放在內(nèi)存中的,如果數(shù)據(jù)量非常大的話,內(nèi)存就有可能不夠用;這種情況下,就可以生成器,例如,python可以用“()”構(gòu)建生成器對(duì)象:

>>> b = (x for x in range(3))
>>> for i in b:
    print(i)

0
1
2
>>> for i in b:
    print(i)
    
>>> 

生成器可以迭代的,并且數(shù)據(jù)實(shí)時(shí)生成,不會(huì)全部保存在內(nèi)存中;值得注意的是,生成器只能讀取一次,從上面的運(yùn)行結(jié)果可以看到,第二次for循環(huán)輸出的結(jié)果為空。

在實(shí)際編程中,如果一個(gè)函數(shù)需要產(chǎn)生一段序列化的數(shù)據(jù),最簡(jiǎn)單的方法是將所有結(jié)果都放在一個(gè)list里返回,如果數(shù)據(jù)量很大的話,應(yīng)該考慮用生成器來(lái)改寫直接返回列表的函數(shù)(Effective Python, Item 16).

>>> def get_generator():
    for i in range(3):
        print("gen ", i)
        yield i
        
>>> c = get_generator()    
>>> c = get_generator()
>>> for i in c:
    print(i)
    
gen  0
0
gen  1
1
gen  2
2

由上面的代碼可以看出,當(dāng)調(diào)用get_generator函數(shù)時(shí),并不會(huì)執(zhí)行函數(shù)內(nèi)部的代碼,而是返回了一個(gè)迭代器對(duì)象,在用for循環(huán)進(jìn)行迭代的時(shí)候,函數(shù)中的代碼才會(huì)被執(zhí)行。
除了使用for循環(huán)獲得生成器返回的值,還可以使用next和send

>>> c = get_generator()
>>> print(next(c))
gen  0
0
>>> print(next(c))
gen  1
1
>>> print(next(c))
gen  2
2
>>> print(next(c))
Traceback (most recent call last):
  File "", line 1, in 
    print(next(c))
StopIteration
>>> c = get_generator()
>>> c.send(None)
gen  0
0
>>> c.send(None)
gen  1
1
>>> c.send(None)
gen  2
2
>>> c.send(None)
Traceback (most recent call last):
  File "", line 1, in 
    c.send(None)
StopIteration

生成器的結(jié)果讀取完后,會(huì)產(chǎn)生一個(gè)StopIteration的異常

2 coroutines中使用

yield一個(gè)常見(jiàn)的使用場(chǎng)景是通過(guò)yield來(lái)實(shí)現(xiàn)協(xié)程,已下面這個(gè)生產(chǎn)者消費(fèi)者模型為例:

def consumer():
    r = "yield"
    while True:
        print("[CONSUMER] r is %s..." % r)
        #當(dāng)下邊語(yǔ)句執(zhí)行時(shí),先執(zhí)行yield r,然后consumer暫停,此時(shí)賦值運(yùn)算還未進(jìn)行
        #等到producer調(diào)用send()時(shí),send()的參數(shù)作為yield r表達(dá)式的值賦給等號(hào)左邊
        n = yield r #yield表達(dá)式可以接收send()發(fā)出的參數(shù)
        if not n:
            return # 這里會(huì)raise一個(gè)StopIteration
        print("[CONSUMER] Consuming %s..." % n)
        r = "200 OK"

def produce(c):
    c.send(None)
    n = 0
    while n < 5:
        n = n + 1
        print("[PRODUCER] Producing %s..." % n)
        r = c.send(n)   #調(diào)用consumer生成器
        print("[PRODUCER] Consumer return: %s" % r)
    c.send(None)    
    c.close()

c = consumer()
produce(c)
[CONSUMER] r is yield...
[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
[CONSUMER] r is 200 OK...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
[CONSUMER] r is 200 OK...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
[CONSUMER] r is 200 OK...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
[CONSUMER] r is 200 OK...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
[CONSUMER] r is 200 OK...
[PRODUCER] Consumer return: 200 OK
Traceback (most recent call last):
  File ".foobar.py", line 51, in 
    produce(c)
  File ".foobar.py", line 47, in produce
    c.send(None)
StopIteration

在上面的例子中可以看到,yield表達(dá)式與send配合,可以起到交換數(shù)據(jù)的效果,

n = yield r

r = c.send(n)
3 contextmanager中使用

另外一個(gè)比較有意思的使用場(chǎng)景是在contextmanager中,如下:

import logging
import contextlib

def foobar():
    logging.debug("Some debug data")
    logging.error("Some error data")
    logging.debug("More debug data")


@contextlib.contextmanager
def debug_logging(level):
    logger = logging.getLogger()
    old_level = logger.getEffectiveLevel()
    logger.setLevel(level)
    try:
        yield #這里表示with塊中的語(yǔ)句
    finally:
        logger.setLevel(old_level)


with debug_logging(logging.DEBUG):
    print("inside context")
    foobar()
print("outside context")
foobar()
inside context
DEBUG:root:Some debug data
ERROR:root:Some error data
DEBUG:root:More debug data
outside context
ERROR:root:Some error data

在上面的代碼中,通過(guò)使用上下文管理器(contextmanager)來(lái)臨時(shí)提升了日志的等級(jí),yield表示with塊中的語(yǔ)句;

總結(jié)

yield表達(dá)式可以創(chuàng)建生成器,應(yīng)該考慮使用生成器來(lái)改寫直接返回list的函數(shù);

由于生成器只能讀取一次,因此使用for循環(huán)遍歷的時(shí)候要格外注意;生成器讀取完后繼續(xù)讀的話會(huì)raise一個(gè)StopIteration的異常,實(shí)際編程中可以使用這個(gè)異常來(lái)作為讀取終止的判斷依據(jù);

yield一個(gè)常見(jiàn)的使用場(chǎng)景是實(shí)現(xiàn)協(xié)程;通過(guò)與send函數(shù)的配合,可以起到交換數(shù)據(jù)的效果;

yield還可以在contextmanager修飾的函數(shù)中表示with塊中的語(yǔ)句;

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/42808.html

相關(guān)文章

  • pythonyield的用法詳解——最簡(jiǎn)單,最清晰的解釋

    摘要:程序執(zhí)行,程序會(huì)從關(guān)鍵字那一行繼續(xù)向下運(yùn)行,會(huì)把這個(gè)值賦值給變量由于方法中包含方法,所以程序會(huì)繼續(xù)向下運(yùn)行執(zhí)行方法,然后再次進(jìn)入循環(huán)程序執(zhí)行再次遇到關(guān)鍵字,會(huì)返回后面的值后,程序再次暫停,直到再次調(diào)用方法或方法。 此文轉(zhuǎn)載,侵刪,原文地址:https://blog.csdn.net/mieleiz... 首先,如果你還沒(méi)有對(duì)yield有個(gè)初步分認(rèn)識(shí),那么你先把yield看做return...

    VPointer 評(píng)論0 收藏0
  • 分布式計(jì)算框架MapReduce

    1 MapReduce概念 和 MapReduce編程模型什么是MapReduce源于Google的MapReduce論文(2004年12月)Hadoop的MapReduce是Google論文的開(kāi)源實(shí)現(xiàn)MapReduce優(yōu)點(diǎn): 海量數(shù)據(jù)離線處理&易開(kāi)發(fā)MapReduce缺點(diǎn): 實(shí)時(shí)流式計(jì)算MapReduce分而治之的思想數(shù)錢實(shí)例:一堆鈔票,各種面值分別是多少單點(diǎn)策略一個(gè)人數(shù)所有的鈔票,數(shù)出各種面值...

    Tecode 評(píng)論0 收藏0
  • Python裝飾器的另類用法

    摘要:今天我們一起探討一下裝飾器的另類用法。語(yǔ)法回顧開(kāi)始之前我們?cè)賹⒀b飾器的語(yǔ)法回顧一下。例子本身只是演示了裝飾器的一種用法,但不是推薦你就這樣使用裝飾器。類裝飾器在以前,還不支持類裝飾器。 之前有比較系統(tǒng)介紹過(guò)Python的裝飾器(請(qǐng)查閱《詳解Python裝飾器》),本文算是一個(gè)補(bǔ)充。今天我們一起探討一下裝飾器的另類用法。 語(yǔ)法回顧 開(kāi)始之前我們?cè)賹ython裝飾器的語(yǔ)法回顧一下。 @d...

    hqman 評(píng)論0 收藏0
  • redux-saga框架使用詳解及Demo教程

    摘要:通過(guò)創(chuàng)建將所有的異步操作邏輯收集在一個(gè)地方集中處理,可以用來(lái)代替中間件。 redux-saga框架使用詳解及Demo教程 前面我們講解過(guò)redux框架和dva框架的基本使用,因?yàn)閐va框架中effects模塊設(shè)計(jì)到了redux-saga中的知識(shí)點(diǎn),可能有的同學(xué)們會(huì)用dva框架,但是對(duì)redux-saga又不是很熟悉,今天我們就來(lái)簡(jiǎn)單的講解下saga框架的主要API和如何配合redux框...

    Nosee 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<