Python生成器及send用法讲解

- 生成器


我们调用一个普通的Python函数时,一般是从函数的第一行代码开始执行,结束于return语句、异常或者函数结束(可以看作隐式的返回None)。一旦函数将控制权交还给调用者,就意味着全部结束。函数中做的所有工作以及保存在局部变量中的数据都将丢失。再次调用这个函数时,一切都将从头创建。

对于在计算机编程中所讨论的函数,这是很标准的流程。这样的函数只能返回一个值,不过,有时可以创建能产生一个序列的函数还是有帮助的。要做到这一点,这种函数需要能够“保存自己的工作”。

我说过,能够“产生一个序列”是因为我们的函数并没有像通常意义那样返回。return隐含的意思是函数正将执行代码的控制权返回给函数被调用的地方。而"yield"的隐含意思是控制权的转移是临时和自愿的,我们的函数将来还会收回控制权。

最初的引入是为了让程序员可以更简单的编写用来产生值的序列的代码

▲.生成值的序列

处理无限序列==>占用内存太大==>遇到问题:函数只有一次返回结果的机会,因而必须一次返回所有的结果==>如果get_primes可以只是简单返回下一个值,而不是一次返回全部的值

一个生成器函数的定义很像一个普通的函数,除了当它要生成一个值的时候,使用yield关键字而不是return。如果一个def的主体包含yield,这个函数会自动变成一个生成器(即使它包含一个return)。除了以上内容,创建一个生成器没有什么多余步骤了。

△生成器就是一类特殊的迭代器。作为一个迭代器,生成器必须要定义一些方法(method),其中一个就是next()。如同迭代器一样,我们可以使用next()函数来获取下一个值。

while循环是用来确保生成器函数永远也不会执行到函数末尾的

PEP 342加入了新的特性

通过send方法来将一个值”发送“给生成器。other = yield foo 这样的语句的意思是,"返回foo的值,这个值返回给调用者的同时,将other的值也设置为那个值

    def get_primes(number):
        while True:
            if is_prime(number):
                number = yield number
            number += 1
    通过这种方式,我们可以在每次执行yield的时候为number设置不同的值。现在我们可以补齐print_successive_primes中缺少的那部分代码:
    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))

- 理解send

    def Get_allprimes(num):
        while True:
            if prime_num(num):
                print(‘num‘,num)
                other = yield num
                print(‘other‘,other)
            num += 1

    gene = Get_allprimes(34)
    gene.send(None)
    gene.send(61)
    output:
    >>>num 37
    >>>other 61
    >>>num 41

★ 重点:看这句xx = yield yy

摘要:send()的作用是使xx赋值为发送的值(send的参数),然后让生成器执行到下个yield..

使用send(params)需要区分情况。△注意:如果生成器未启动,则必须在使用send()前必须要启动生成器,而启动的方法可以是generator.next()或是generator.send(None)执行到第一个yield处.之后就可以使用send(params)不断传入值了。如果是已启动,则send(params)的作用就是给xx赋值为发送的值(send的参数),然后让生成器执行到下个yield..

为什么需要send(None),也很好理解,因为 生成器还没有走到第一个yield语句,如果我们发生一个真实的值,这时是没有人去“接收”它的。一旦生成器启动了,就对象接受(即=号左边的左值xx接受了),之后就可以使用send(params)不断传入值了

▲注意,每次的send()都会运行到yield语句,但赋值不会执行,只会有返回值,相当于return后就退出函数了,所以在返回值之后的赋值就不会执行了。

在我看来send()的作用是在next()的基础上,多了个给xx赋值的功能。如第二次的gene.send(61)先从上次停住的yield处开始运行,使other 赋值为61,然后执行到下一个yield处===>可以看出当send方法的参数为None时,它与next方法完全等价

More(给还未懂的人更详细的讲解):
  • send(None)启动后send(int类参数),然后再传个send(None)效果是怎样的?
    def Gene():         #生成器函数
        print("ok")
        x = 100
        print(x)
        first = yield 50    #这里就是send函数的关键
        # send所传递的值其实就是给 =号左边的左值赋值
        print(first)

        second = yield x  # 这里试第二个断点
        print(second)

        z = ‘third‘
        third = yield z
        print(third)

    inst = Gene()                   #创建生成器对象
    output1 = inst.send(None)       #启动生成器,运行到第一个yield
    print(output1)                 #这边的output1获得的是yield的返回值 50
    output2 = inst.send(30)
    print(output2)
    output3 = inst.send(None)

    output:
    >>>ok
    >>>100      ==>print(x)
    >>>50       ==>print(output1)
    >>>30       ==>send(30)后first被赋值为30然后print(first)
    >>>100      ==>print(output2) ==>output = x==100
    >>>None     ==>send(None)second被赋值为None,print(second)==>None
每次的send(params)都会运行到yield语句,但赋值不会执行,只会有返回值。赋值在下一次send(params)时将xx赋值为params,执行过程如下

只有返回值:

output1接受返回值:


执行send(params):

将passvalue赋值为params:

接受运行到的第二个yield的返回值:

参考博客生成器

原文地址:https://www.cnblogs.com/nymrli/p/9416949.html

时间: 2024-10-08 01:10:01

Python生成器及send用法讲解的相关文章

python中yield的用法及生成器的理解

首先我要吐槽一下,看程序的过程中遇见了yield这个关键字,然后百度的时候,发现没有一个能简单的让我懂的,讲起来真TM的都是头头是道,什么参数,什么传递的,还口口声声说自己的教程是最简单的,最浅显易懂的,我就想问没有有考虑过读者的感受. 接下来是正题: 首先,如果你还没有对yield有个初步分认识,那么你先把yield看做“return”,这个是直观的,它首先是个return,普通的return是什么意思,就是在程序中返回某个值,返回之后程序就不再往下运行了.看做return之后再把它看做一个是

【Python 生成器 匿名函数 递归 模块及包的导入 正则re】

一.生成器 1.定义 生成器(generator)是一个特殊的迭代器,它的实现更简单优雅,yield是生成器实现__next__()方法的关键.它作为生成器执行的暂停恢复点,可以对yield表达式进行赋值,也可以将yield表达式的值返回. 也就是说,yield是一个语法糖,内部实现支持了迭代器协议,同时yield内部是一个状态机,维护着挂起和继续的状态. yield的功能: 1.相当于为函数封装好__iter__和__next__ 2.return只能返回一次值,函数就终止了,而yield能返

Python生成器 百日筑基之堵漏

生成器 函数体内有yield选项的就是生成器,生成器的本质是迭代器,由于函数结构和生成器结构类似,可以通过调用判断是函数还是生成器.如下: def fun(): yield "我是生成器" print(fun()) # 打印内容如下: <generator object fun at 0x0000000002160ED0> 生成器的优点就是节省内存.Python获取生成器的二种方式: 通过函数获取生成器 通过生成器推导式创建生成器 通过函数获取生成器 def fun():

Python关于yield的用法

Python中有两个用法比较经典,一个是装饰器,另一个就是yield(生成器)了,装饰器顾名思义就是装饰某东西的,这个东西就是函数,简单的说就是把函数当成该装饰器的参数然后返回一个函数. 最近接触到了yield字段,这个真是太好用了,它就像range和xrange的区别差不多,好多人用range函数,但他们并不知道range函数返回一个list,而他并不需要这个list,所以这时候xrange就上场了,同样的道理,yield也是为了同样的原理而生,由于我是刚刚接触所以还在研究中,下面这几篇文章写

4.Python 生成器yield

常用方法: next    获取下一个值 send    发送值到生成器 throw  发送异常到生成器 python生成器模拟线程并发:

python中yield的用法详解——最简单,最清晰的解释

本文收自:冯爽朗 ,下面有博主名片 个人分类: python 首先我要吐槽一下,看程序的过程中遇见了yield这个关键字,然后百度的时候,发现没有一个能简单的让我懂的,讲起来真TM的都是头头是道,什么参数,什么传递的,还口口声声说自己的教程是最简单的,最浅显易懂的,我就想问没有有考虑过读者的感受. 接下来是正题: 首先,如果你还没有对yield有个初步分认识,那么你先把yield看做"return",这个是直观的,它首先是个return,普通的return是什么意思,就是在程序中返回某

Python 生成器和协程

Python3 迭代器与生成器 迭代器 迭代是Python最强大的功能之一,是访问集合元素的一种方式. 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退. 迭代器有两个基本的方法:iter() 和 next(). 字符串,列表,元组,集合.字典.range().文件句柄等可迭代对象(iterable)都可用于创建迭代器: 内部含有__iter__()方法的就是可迭代对象,遵循可迭代协议. 可迭代对象.__iter__

Python 生成器和推导式

一.Python生成器和生成器函数1.生成器和生成器函数的概念    1.生成器的本质是迭代器    2.函数中包含yield,就是生成器函数 2.生成器函数的写法    def func():        a =10        yield 20    gen = func()  #没有执行,而是生成一个生成器    普通函数和生成器函数的不同    1.普通函数名()表示函数的的执行    2.生成器函数名()不是函数的执行,而是生成一个生成器 yield和return的不同    1.

python之模块py_compile用法(将py文件转换为pyc文件)

# -*- coding: cp936 -*- #python 27 #xiaodeng #python之模块py_compile用法(将py文件转换为pyc文件) #二进制文件,是由py文件经过编译后,生成的文件. ''' import py_compile #不带转义r py_compile.compile('D:\test.py') Traceback (most recent call last): File "<pyshell#1>", line 1, in &l