Python中Generators教程
要想创建一个iterator,必须实现一个有__iter__()和__next__()方法的类,类要能够跟踪内部状态并且在没有元素返回的时候引发StopIteration异常.
这个过程很繁琐而且违反直觉.Generator能够解决这个问题.
python generator是一个简单的创建iterator的途径.前面讲的那些繁琐的步骤都可以被generator自动完成.
简单来说,generator是一个能够返回迭代器对象的函数.
怎样创建一个python generator?
就像创建一个函数一样简单,只不过不使用return 声明,而是使用yield声明.
如果一个函数至少包含一个yield声明(当然它也可以包含其他yield或return),那么它就是一个generator.
yield和return都会让函数返回一些东西,区别在于,return声明彻底结束一个函数,而yield声明是暂停函数,保存它的所有状态,并且后续被调用后会继续执行.
generator函数和普通函数的区别
- generator函数包含一个以上的yield声明
- generator函数被调用的时候,会返回一个iterator对象,但是函数并不会立即开始执行
- __iter__()和__next__()方法被自动实现,所以可以使用next()函数对返回的此iterator对象进行迭代
- 一旦一个generator 执行到yield语句,generator函数暂停,程序控制流被转移到调用方
- 在对generator的连续调用之间,generator的本地变量和状态会被保存
- 最终,generator函数终止,再调用generator会引发StopIteration异常
下面这个例子说明上述全部要点,我们有一个名为my_gen()的函数,它带有一些yield声明.
# A simple generator function
def my_gen(): n = 1 print('This is printed first') # Generator function contains yield statements yield n n += 1 print('This is printed second') yield n n += 1 print('This is printed at last') yield n
有趣的是,在这个例子里变量n在每次调用之间都被记住了。和一般函数不同的是,在函数yield之后本地变量没有被销毁,而且,generator对象只能被这样迭代一次。
要想重复上面的过程,需要类似 a = my_gen() 这样创建另一个generator对象,并对其使用next方法迭代。
注意
:我们可以对generator对象直接使用for循环。
这是因为一个for循环接收一个iterator对象,且使用next()函数迭代它,当遇到StopIteration异常的时候自动停止。
# A simple generator function
def my_gen(): n = 1 print('This is printed first') # Generator function contains yield statements yield n n += 1 print('This is printed second') yield n n += 1 print('This is printed at last') yield n # Using for loop # Output:
# This is printed first
# 1
# This is printed second
# 2
# This is printed at last
# 3 for item in my_gen(): print(item)
有循环的python generator
上面的例子没有实际的应用意义,我们只是为了探究背后原理。
通常来说,generator都是和循环结合实现的,且这个循环带有一个终止条件。
我们来看一个reverse一个字符串的例子
def rev_str(my_str): length = len(my_str) for i in range(length - 1,-1,-1): yield my_str[i] # For loop to reverse the string
# Output:
# o
# l
# l
# e
# h
for char in rev_str("hello"): print(char)
我们在for循环里面使用range()函数来获取反向顺序的index。
generator除了可以应用于string,还可以应用于其它类型的iterator,例如list,tuple等。
python generator 表达式
使用generator表达式可以很容易地创建简单的generator。
就像lambda函数可以创建匿名函数一样,generator函数创建一个匿名generator函数。
generator表达式的语法类似于python的list comprehension,只是方括号被替换为了圆括号而已。
list comprehension和generator表达式的主要区别在于,前者产生全部的list,后者每次仅产生一项。
它们有些懒惰,仅在接到请求的时候才会产生输出。因此,generator表达式比list comprehension更加节省内存。
# Initialize the list
my_list = [1, 3, 6, 10] # square each term using list comprehension
# Output: [1, 9, 36, 100]
[x**2 for x in my_list] # same thing can be done using generator expression
# Output: <generator object <genexpr> at 0x0000000002EBDAF8>
(x**2 for x in my_list)
上面的例子中,generator表达式没有立即产生需要的结果,而是在需要产生item的时候返回一个generator对象。
# Intialize the list
my_list = [1, 3, 6, 10] a = (x**2 for x in my_list)
# Output: 1
print(next(a)) # Output: 9
print(next(a)) # Output: 36
print(next(a)) # Output: 100
print(next(a)) # Output: StopIteration
next(a)
generator表达式可以在函数内部使用。当这样使用的时候,圆括号可以丢弃。
python里为什么要使用generator?
1.容易实现
相对于iterator类来说,generator的实现清晰、简洁。下面是用iterator实现一个2的指数函数
class PowTwo: def __init__(self, max = 0): self.max = max def __iter__(self): self.n = 0 return self def __next__(self): if self.n > self.max: raise StopIteration result = 2 ** self.n self.n += 1 return result
generator这样实现
def PowTwoGen(max = 0): n = 0 while n < max: yield 2 ** n n += 1
因为generator自动跟踪实现细节,因此更加清晰、简洁。
2.节省内存
一个函数返回一个序列(sequence)的时候,会在内存里面把这个序列构建好再返回。如果这个序列包含很多数据的话,就过犹不及了。
而如果序列是以generator方式实现的,就是内存友好的,因为他每次只产生一个item。
3.代表无限的stream
generator是一个很棒的表示无限数据流的工具。无限数据流不能被保存在内存里面,并且因为generator每次产生一个item,它就可以表示无限数据流。
下面的代码可以产生所有的奇数
def all_even(): n = 0 while True: yield n n += 2
4.generator流水线(pipeline)
generator可以对一系列操作执行流水线操作。
假设我们有一个快餐连锁店的日志。日志的第四列是每小时售出的披萨数量,我们想对近5年的这一数据进行求和。
假设所有数据都是字符,不可用的数据都以"N/A"表示,使用generator可以这样实现
with open('sells.log') as file: pizza_col = (line[3] for line in file) per_hour = (int(x) for x in pizza_col if x != 'N/A') print("Total pizzas sold = ",sum(per_hour))
这个流水线既高效又易读,并且看起来很酷!:)
相关文章:
Python中Generators教程
要想创建一个iterator,必须实现一个有__iter__()和__next__()方法的类,类要能够跟踪内部状态并且在没有元素返回的时候引发StopIteration异常. 这个过程很繁琐而且违反直觉.Generator能够解决这个问题. python generator是一个简单的创建iterator的途径…...
数据结构与算法基础-学习-10-线性表之栈的清理、销毁、压栈、弹栈
一、函数实现1、ClearSqStack(1)用途清理栈的空间。只需要栈顶指针和栈底指针相等,就说明栈已经清空,后续新入栈的数据可以直接覆盖,不用实际清理数据,提升了清理效率。(2)源码Statu…...

Leetcode 每日一题 1234. 替换子串得到平衡字符串
Halo,这里是Ppeua。平时主要更新C语言,C,数据结构算法......感兴趣就关注我吧!你定不会失望。 🌈个人主页:主页链接 🌈算法专栏:专栏链接 我会一直往里填充内容哒! &…...

【MYSQL中级篇】数据库数据查询学习
🍁博主简介 🏅云计算领域优质创作者 🏅华为云开发者社区专家博主 🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 相关文章 文章名文章地址【MYSQL初级篇】入门…...
华为OD机试真题JAVA实现【火星文计算】真题+解题思路+代码(20222023)
🔥系列专栏 华为OD机试(JAVA)真题目录汇总华为OD机试(Python)真题目录汇总华为OD机试(C++)真题目录汇总华为OD机试(JavaScript)真题目录汇总文章目录 🔥系列专栏题目输入输出描述示例一输入输出说明解题思路核心知识点Code运行结果版...
Linux基础知识
♥️作者:小刘在C站 ♥️个人主页:小刘主页 ♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生! ♥️夕阳下,是最美的绽放࿰…...

Linux 游戏性能谁的 更优秀X.Org还是Wayland!
导读X.Org 和 Wayland 是目前 Linux 平台上的两大主流显示服务器,那么两者在 Linux 游戏性能上谁更优秀呢?国外科技媒体 Phoronix 在 Ubuntu 22.10 上对其进行了多款游戏的实测。评测在运行 GNOME 43.1 的 Ubuntu 22.10 上进行测试,在安装英伟…...

【数据结构】算法的复杂度分析:让你拥有未卜先知的能力
👑专栏内容:数据结构⛪个人主页:子夜的星的主页💕座右铭:日拱一卒,功不唐捐 文章目录一、前言二、时间复杂度1、定义2、大O的渐进表示法3、常见的时间复杂度三、空间复杂度1、定义2、常见的空间复杂度一、前…...

Linux根文件系统移植
目录 一、根文件系统 1.1根文件系统 1.2根文件系统内容 二、根文件系统移植 2.1BusyBox 2.2BusyBox的获取 2.3BusyBox的使用 2.4make menuconfig 2.5编译和安装 2.6修改根文件系统 一、根文件系统 1.1根文件系统 根文件系统是内核启动后挂载的第一个文件系统系统引…...

Three.js 无限平面快速教程【Plane】
Three.js 提供了 Plane 概念来表示在 3d 空间中无限延伸的二维表面。 这对于光标交互很有用,因此你可能需要了解如何设置此平面、将其可视化并根据需要进行调整。 推荐:使用 NSDT场景设计器 快速搭建 3D场景。 Three.js 的 Plane 文档很好而且准确&…...

在线预览PDF文件、图片,并且预览地址不显示文件或图片的真实路径。
实现在线预览PDF文件、图片,并且预览地址不显示文件或图片的真实路径。1、vue使用blob流在线预览PDF、图片(包括jpg、png等格式)。1、按钮的方法:2、方法详细:(此方法可以在发起请求时携带token,…...

Allegro如何设置导入Subdrawing可自由选择目录操作指导
Allegro如何设置导入Subdrawing可自由选择目录操作指导 用Allgro做PCB设计的时候,导入Subdrawing是非常常用的功能,在导入Subdrawing的时候,通常需要把Subdrawing文件放在需要导入PCB的相同目录下,不能自由选择,如下图 但是Allegro是支持自由选择目录的,只需按照下方的步…...

SpirngMVC执行原理--自学版
DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心,用户发出请求,DispatcherServlet接收请求并拦截请求HandlerMapper为处理器映射。DispatcherServlet调用。HandlerMapping根据请求url查找HandlerHandlerExecution表示具体的Handl…...
获取savemodel的输入输出节点
saved_model_cli show --dir savemodels --all 结果: MetaGraphDef with tag-set: ‘serve’ contains the following SignatureDefs: signature_def[‘translation_signature’]: The given SavedModel SignatureDef contains the following input(s): inputs[‘i…...

《Learning to Reconstruct Botanical Trees from Single Images》学习从单幅图像重建植物树
读书报告下载https://download.csdn.net/download/weixin_43042683/87448211论文原文https://dl.acm.org/doi/10.1145/3478513.3480525论文视频https://www.bilibili.com/video/BV1cb4y127Vp/?fromseopage&vd_source5212838c127b01db69dcc8b2d27ca5171引言植物存在在室外与…...

vant 4 正式发布,支持暗黑主题,那么是如何实现的呢
2022年10月25日首发于掘金,现在同步到公众号。11. 前言大家好,我是若川。我倾力持续组织了一年多源码共读,感兴趣的可以加我微信 lxchuan12 参与。另外,想学源码,极力推荐关注我写的专栏《学习源码整体架构系列》&…...
MySQL的复制 二
复制是MySQL的一项功能,使服务器能够将更改从一个实例恢复到另一个实例 主服务器(master)将所有数据和结构更改记录到二进制日志中。二进制日志格式是基于语句的、基于行的和混合的。 从属服务器(slave)从主服务器请求…...

秒杀项目之秒杀商品展示及商品秒杀
目录前言一、登录方式调整二、生成秒杀订单2.1 绑定秒杀商品2.2 查看秒杀商品2.3 订单秒杀2.3.1 移除seata相关(方便测压)2.3.2 生成秒杀订单2.3.3 前端页面秒杀测试注意前言 博主博客用到的资源都会同步分享到资源包中 一、登录方式调整 第1步…...

教育行业需要什么样的数字产品?
数字化转型的浪潮已经席卷了各行各业,不仅出现在互联网、电商、建筑等行业,还应用在了教育行业。数字化的教育ERP软件能够在满足学校需求的基础上,帮助学校完善各类工作流程,提高工作效率。 对于一个拥有多个校区,上万…...

Spring MVC
一、Spring MVC介绍 a. Spring MVC是一个Web框架 b. Spring MVC是基于Servlet API构成的 MVC 是 Model View Controller 的缩写。 MVC 是⼀种思想,⽽ Spring MVC 是对 MVC 思想的具体实现。 学习Spring MVC目标: a.连接功能:将用户ÿ…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...

Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...