Python 生成器 (通俗讲解)

2023-05-16

一、生成器的本质

生成器是含有yield语句(或yield表达式)的函数所返回的对象。也就是说,要创建一个生成器,我们首先要定义一个函数,该函数内将使用yield表达式或yield语句来表示每次生成的值。该函数的返回值是一个生成器对象,通过把这个函数的返回值赋给一个变量,我们就得到了一个生成器对象变量,对这个对象进行send和next等操作,即可实现生成器的功能。

如下代码创建了一个最简单的生成器。

def g():
    while True:
        yield 1

a = g()

创建生成器之前,需要编写一个含有yield的函数,这是一种特殊的函数。当该函数被调用时,并不会立即执行函数中语句,而是直接返回一个生成器对象。后续的操作都可以通过生成器对象进行执行。

在这里,变量a就是一个生成器对象。

二、使用next()

next函数可用于引起生成器/迭代器的下一次生成/迭代。其返回值就是下一个生成的值。通过 next(generator) 这一方式,可以获得一系列值。

def g():
    a=1
    while True:
        yield a
        a+=1

a=g()
print(next(a))
print(next(a))
print(next(a))

'''
输出:
1
2
3
'''

由示例可见,输出结果为分别为1,2,3. 对于该过程的解释如下:

每调用一次next(a),都将执行g()函数,执行到yield处时,g()函数暂停,并将yield后的表达式作为next(a)的返回值返回。此后继续调用next(a)时,将从上一次g()函数中的暂停处继续运行,直到来到下一个yield,并执行同样的操作,依次类推。

三、StopIteration异常

在第二节中探讨的生成器采用了while True循环,这一生成器可生成的元素是无限多的,但也有只能产出有限个值的生成器,如下例所示:

def g():
    yield 1
    yield 2

a=g()
print(next(a))
print(next(a))
print(next(a))

该生成器最多产出两个元素,因此在执行最后一个(即第三个)print语句时,将会报错,引发StopIteration异常。

换言之,如果生成器中运行g()函数直到结束还没有yield出现,就会发生StopIteration异常。因此,如果在生成器对应的函数中应用return语句,也会产生同样的效果:

def g():
    if(t != 0):
        yield t
    else:
        return


a = g()

t = 1
print(next(a))
t = 0
print(next(a))  # g()在yield之前就已经return了,所以这里会报错

四、生成器函数传参

用于生成器的函数可以携带参数,此时在定义生成器对象时可以带参调用函数,如下所示:

def g(value=0,step=1):
    while True:
        yield value
        value += step


a = g(1,2)

print(next(a))
print(next(a))
print(next(a))
'''
输出:
1
3
5
'''

五、生成器方法send()

这是生成器中一个相对比较难理解的概念。笔者在初学时查阅了很多资料,百思不得其解。但通过简单的代码实验,就了解了send()的使用方法。send()函数可以接收一个参数发送(该参数可以是任意类型的,如字符串、数字、列表等)。

此时,yield作为表达式,而不是语句出现在生成器对应的函数中。

来看下面的示例:

def g():
    t = yield 1
    yield t

a=g()
print(next(a))
print(a.send("test"))
'''
输出:
1
test
'''

对于本例,可作出如下解释:

第一次print:调用next(a),g()函数执行到t=yield 1暂停(准确的来说由于赋值表达式是从右往左运算的,因此运行到yield 1这个地方就会暂停,此时还没有进行赋值操作),和上例一样,yield充当语句的角色,next()函数返回1,因此打印结果为1

第二次print:调用send("test"),此时,暂停处的 yield 1 将会充当表达式的角色,这个特殊的表达式的值为send函数的参数——即"test",然后t就被赋值为了"test",g()从该处继续运行,直到遇到下一个yield——即yield t语句,send()函数返回t的值,即打印出了test.

从这个例子当中,大家可以思考一个问题send()和next()有什么联系和区别?首先,在形式上,next是函数,可针对迭代器、生成器进行操作,所以语法是next(a)。而send()是生成器独有的方法, 语法是a.send(something)。 此外,send发送一个参数,使得暂停处的yield充当表达式的角色,并通过send()函数传入的参数决定yield表达式的值。

两者的共同点在于,他们都从上一次yield暂停处继续程序,运行到达下一个yield处,并返回该处yield后的值。

值得指出的是,初次使用生成器的时候,由于还没有“上一个yield”,所以不可以通过send()函数传入消息。因此只能使用next(a)。当然,如果非要使用send的话,传入一个None参数,即a.send(None)也是被允许的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 生成器 (通俗讲解) 的相关文章

随机推荐

  • Linux 运行shell文件,出现 $‘\r‘: command not found

    运行编写的shell脚本时 xff0c 出现了 r command not found 这样的错误提示 报错的原因是我们在windows系统操作时 xff0c 编辑器里的换行符是 r n xff0c 而Linux上为 n xff0c 两个系
  • [Swoole] 在Ubuntu下安装、快速开始

    本文主要讲述在 Ubuntu 下编译安装 Swoole xff0c 并根据官方文档给出的demo进行了测试和搬运 xff0c 包括 xff1a TCP服务器 UDP服务器 HTTP服务器 WebSocket服务器 异步客户端 定时器和协程相
  • C++ 快速幂取模算法

    快速求 b p k的值 1 模运算与乘法的性质 乘积取模可以在乘之前先取模 x y d 61 x d y d d 比如 xff1a a a c 61 a c a c c 2 本题公式 当 b为偶数时 xff1a ab mod c 61 a2
  • [Python] socket实现TFTP上传和下载

    Python socket实现TFTP上传和下载 一 说明二 TFTP协议介绍 xff08 参考网络 xff0c 详情可搜索 xff09 2 1 特点 2 2 TFTP下载过程分析 xff1a 2 3 TFTP操作码与数据格式 xff1a
  • [Python] 通过采集两万条数据,对《无名之辈》影评分析

    一 说明 本文主要讲述采集猫眼电影用户评论进行分析 xff0c 相关爬虫采集程序可以爬取多个电影评论 运行环境 xff1a Win10 Python3 5 分析工具 xff1a jieba wordcloud pyecharts matpl
  • [Python] 用python做一个游戏辅助脚本,完整思路

    一 说明 简述 xff1a 本文将以4399小游戏 宠物连连看经典版2 作为测试案例 xff0c 通过识别小图标 xff0c 模拟鼠标点击 xff0c 快速完成配对 对于有兴趣学习游戏脚本的同学有一定的帮助 运行环境 xff1a Win10
  • cp命令 复制多个目录/文件夹下文件到指定目录

    可以使用cp命令的通配符和递归选项来复制多个目录下多个文件夹下的文件到指定目录 如果目标目录不存在 xff0c 可以使用 mkdir p命令来创建目录 p 选项表示递归创建目录 xff0c 如果目录已经存在 xff0c 则不会报错 例如 x
  • 网络安全传输系统(3)—OpenSSL加密传输

    1 基本介绍 1 1 未加密传输的安全弊端 如果在网络传输中没有加密 xff0c 就是以明文传输 传输的数据可以被抓包软件直接截获 xff0c 并能读取里面的数据 1 2 加密基本原理 对称加密 xff1a 对称加密指的就是加密和解密使用同
  • 网络安全传输系统(4)—线程池优化

    服务器单发模式 初始化 gt 等待连接 gt 处理请求 gt 关闭连接 gt 再次等待连接服务器并发模式 初始化 gt 等待连接 gt 交给子进程处理请求 gt 再次等待连接单发服务器不能同时处理多个客户端请求 xff0c 并发服务器则可以
  • 网络安全传输系统(5)—账号管理子系统设计

    1 登录模块设计 输入用户名和密码根据用户名从数据库提取密码比较用户输入密码和数据库提取密码 xff0c 以决定是否登录成功 2 编译客户端程序 arm linux gcc L 008 openssl 1 0 0s install lib
  • C语言实例—一个数如果恰好等于它的因子之和,这个数就称为完数。(gcc编译)

    1 题目 一个数如果恰好等于它的因子之和 xff0c 这个数就称为完数 例如 xff0c 6的因子是1 xff0c 2 xff0c 3 xff0c 而6 61 1 43 2 43 3 xff0c 因此6为完数 编程序找出1000之内所有的完
  • C语言实例—输入两个正整数m和n,求其最大公约数和最小公倍数(gcc 编译)。

    1 辗转相除法 辗转相除法是古希腊求两个正整数的最大公约数的 xff0c 也叫欧几里德算法 xff0c 其方法是用较大的数除以较小的数 xff0c 上面较小的除数和得出的余数构成新的一对数 xff0c 继续做上面的除法 xff0c 直到出现
  • Linux线程详解

    并行和并发的区别 1 并发 concurrency xff1a 在操作系统 中 xff0c 是指一个时间段中有几个程序都处于已启动运行到运行完毕之间 xff0c 且这几个程序都是在同一个处理机上运行 其中两种并发关系分别是同步 和互斥 xf
  • 数据结构—带头结点的单循环链表

    1 基本操作 循环链表的特点是最后一个元素的指针域指向头结点 因此对于循环链表的初始化 xff08 设表的头结点是L xff0c 不再是L gt next 61 NULL xff0c 而是L gt next 61 L 循环链表为空时 xff
  • 数据结构—有序表的合并

    1 有序表合并 问题描述 xff1a 已知线性表La 和Lb中的数据元素按值非递减 有序排列 xff0c 现要求将La和Lb归并为一个新的线性表Lc xff0c 且Lc中的数据元素仍按值非递减有序排列 例如 xff1a La 61 1 7
  • 数据结构—习题2.6 通过一趟遍历找出单链表中的最大值

    1 题目描述 设计一个算法 xff0c 通过一趟遍历在单链表中确定值最大的结点 2 题目分析 假定第一个结点中数据具有最大值 xff0c 依次与下一个元素比较 xff0c 若其小于下一个元素 xff0c 则设其下一个元素为最大值 xff0c
  • 【MySQL 11】怎么解决MySQL 8.0.18 大小写敏感问题

    1 查看状态 通过 show variables 命令查看当前 mysql 是否是区分大小写 xff0c 如下 xff1a mysql大小写敏感配置相关的两个参数 xff0c lower case file system 和 lower c
  • Ubuntu配置阿里云ddns

    首发于yuany3721的WordPress 生成阿里云access key 注意 xff1a 不能使用ram子用户 下载并配置ddns curl https github com NewFuture DDNS releases downl
  • LibreOJ - 10015 扩散

    题目描述 一个点每过一个单位时间就会向 4 个方向扩散一个距离 xff0c 如图所示 xff1a 两个点 a b 连通 xff0c 记作 e a b xff0c 当且仅当 a b 的扩散区域有公共部分 连通块的定义是块内的任意两个点 u v
  • Python 生成器 (通俗讲解)

    一 生成器的本质 生成器是含有yield语句 xff08 或yield表达式 xff09 的函数所返回的对象 也就是说 xff0c 要创建一个生成器 xff0c 我们首先要定义一个函数 xff0c 该函数内将使用yield表达式或yield