'yield'和生成器解释

本片笔记学习自:Improve Your Python: 'yield' and Generators Explained

A Python generator is a function which returns a generator iterator (just an object we can iterate over) by calling yield. yield may be called with a value, in which case that value is treated as the "generated" value. The next time next() is called on the generator iterator (i.e. in the next step in a for loop, for example),Rthe generator resumes execution from where it called yield, not from the beginning of the function. All of the state, like the values of local variables, is recovered and the generator contiues to execute until the next call to yield.

  • 子程序(subroutine)
    一些时候,我们想要创建一个可以不断得到一系列值的函数,而不是一个值(return),为了做到这样子,这个函数首先要能够保存上下文。
    注意return、yield的不同:return返回None或者某个值,并且将控制权归还到调用前附近的代码段;yield则更多地是我们希望连续不断的获取。
    有yield能力的“函数”叫做生成器.

  • 生成器的作用
    动态生成一系列的数。

  • 迭代器、生成器
    生成器是一种迭代器,生成器必须要有next().

To get the next value from a generator, we use the same built-in function as for iterators: next().next() takes care of calling the generator's next() method). Since a generator is a type of iterator, it can be used in a for loop.

为了从生成器中获取一个值,我们必须使用相同的内嵌函数next(),这个函数会调用生成器/迭代器的next()方法,我们可以在for循环中使用生成器。

The easiest way to remember what yield does is to think of it as return (plus a little magic) for generator functions.**

  • 生成器的例子:
>>> def simple_generator_function():
>>>    yield 1
>>>    yield 2
>>>    yield 3

>>> for value in simple_generator_function():
>>>     print(value)
1
2
3

>>> our_generator = simple_generator_function()
>>> next(our_generator)
1
>>> next(our_generator)
2
>>> next(our_generator)
3
  • 当生成器函数退出的时候会有一个StopIteration异常。

  • send:发送数据给生成器。
    有时我们需要跟生成器进行一些交互,我们不仅仅要从生成器中得到一些值,还想给生成器发送一些值。

假设我们要打印出大于1、10、100、1000...等的最小整数,代码如下,###########表示打印调试信息,可以不看:

import math

def is_prime(number):
    if number > 1:
        if number == 2:
            return True
        if number % 2 == 0:
            return False
        for current in range(3, int(math.sqrt(number) + 1), 2):
            if number % current == 0:
                return False
        return True
    return False

def get_primes(number):
    print(str(number)+'-1')    ###########
    while True:
        print(str(number)+'-2') ###########
        if is_prime(number):
            print(str(number)+'-3') ###########
            number = yield number
            print(str(number)+'-4') ###########
        number += 1
        print(str(number)+'-5') ###########

def print_successive_primes(iterations, base=10):
    prime_generator = get_primes(base)
    prime_generator.send(None)
    for power in range(iterations):
        print(prime_generator.send(base ** power))

print_successive_primes(10)

首先我们只调用prime_generator = get_primes(base)启动生成器,这个时候我们没有做什么,仅仅只是启动生成器;
接着我们调用prime_generator.send(None),打印出如下的信息,这说明发送None只是为了让生成器第一次运行到yield语句(包括yield)。

10-1
10-2
11-5
11-2
11-3

接着我们调用10次prime_generator.send(base ** power),每次都是主流程发送值过去,生成器收到的同时发送一个数据回来,主流程收到数据。这个过程就像调用函数一样,只不过这次我们可以加参数进去了!!!

  • 生成器的威力
import random

def get_data():
    """Return 3 random integers between 0 and 9"""
    return random.sample(range(10), 3)

def consume():
    """Displays a running average across lists of integers sent to it"""
    running_sum = 0
    data_items_seen = 0

    while True:
        data = yield
        data_items_seen += len(data)
        running_sum += sum(data)
        print('The running average is {}'.format(running_sum / float(data_items_seen)))

def produce(consumer):
    """Produces a set of values and forwards them to the pre-defined consumer
    function"""
    while True:
        data = get_data()
        print('Produced {}'.format(data))
        consumer.send(data)
        yield

if __name__ == '__main__':
    consumer = consume()
    consumer.send(None)
    producer = produce(consumer)

    for _ in range(10):
        print('Producing...')
        next(producer)

要理解以上的代码,可以将代码分成两部分的功能:一部分是生成,一部分是消费。
主函数里面启动生产,每生产一个喂给消费者一个,消费者消费后得出一个结果。主函数控制生产,生产控制消费。
produce是一个生成器,yield只是为了让produce运行一次停一次,好将生成数据进行消费;
consume也是一个生成器,这里yield只是为了得到数据,然后消费,然后又继续等待数据,还是蛮被动的。

  • 总结:
    There are a few key ideas I hope you take away from this discussion:
    generators are used to generate a series of values
    yield is like the return of generator functions
    The only other thing yield does is save the "state" of a generator function
    A generator is just a special type of iterator
    Like iterators, we can get the next value from a generator using next()
    for gets values by calling next() implicitly
    I hope this post was helpful. If you had never heard of generators, I hope you now understand what they are, why they're useful, and how to use them. If you were somewhat familiar with generators, I hope any confusion is now cleared up.

  • 拓展阅读:
    看完这篇,你就知道Python生成器是什么

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • title标题: A Web Crawler With asyncio Coroutinesauthor作者: A...
    彰乐乐乐乐阅读 1,967评论 0 8
  • 你不需要再讲什么道理 兀地坐下来 看看窗外的树 沉默,等待不远处的雨 温度下降,湿度上升 升起炉膛的柴火 听那爆裂...
    shadowunique阅读 127评论 0 3
  • 在她的记忆里,父亲像头黄牛,勤劳质朴,缺乏诗情画意; 在她的意识里,父亲像个老古董,固执呆板,不懂人情...
    Trista蒲公英阅读 334评论 2 6
  • LM7:大家晚上好,我是耐心,今天跳了皮筋,跳了大绳,转了呼啦圈,踢了键子,玩了橡皮泥,玩口袋打人,我爱我自己,今...
    心羽暖姐姐阅读 163评论 0 0
  • 如果有人问我,有什么好书推荐,我会毫不犹豫的推荐《失控》,从2009年开始,它便成了我人生中一本非常重要的书,虽然...
    96a6695b09c9阅读 1,586评论 0 1