Python深入理解迭代器和生成器

当说起Python里面的高级特性时,就不能不提迭代器(Iterators)和生成器(Generators)啦!它们就像是处理数据的一把利器,特别是对付大数据的时候,简直就是神器!咱们今天就来聊聊它们到底是啥,怎么用,还有点啥实际用途吧!

目录

1. 迭代器(Iterators)

2. 使用迭代器

3. 自定义迭代器

4. 生成器(Generators)

5. 生成器 vs. 列表推导式

6. 生成器的惰性计算(Lazy Evaluation)

7. 生成器的状态管理

8. 生成器的并发与异步

总结


1. 迭代器(Iterators)

什么是迭代器?

迭代Python 最强大的功能之一,而迭代器(Iterators)是一种用于遍历集合对象。它能记住遍历的位置,并提供一个方法来访问集合中的下一个元素。有两个特点:

  • 只能向前遍历,不能后退。
  • 使用 for 循环或 next() 函数进行遍历。

迭代器的工作原理:

迭代器的工作原理是实现迭代器协议。该协议定义了两个方法:

  • iter(): 返回一个新的迭代器对象。
  • next(): 返回迭代器中的下一个元素。

当迭代器到达集合的末尾时,next() 方法会抛出 StopIteration 异常。

以下是一些可迭代对象的示例:

  • 列表
  • 元组
  • 字符串
  • 字典
  • 集合

2. 使用迭代器

下面通过两个例子讲一下迭代器。

示例1:使用 for 循环来遍历迭代器。

my_list = [1, 2, 3, 4, 5] #这里的集合是一个列表# 使用 for 循环遍历列表
for item in my_list:print(item)

该代码使用 while True 循环来遍历迭代器。在循环体内,它使用 next() 方法获取迭代器的下一个元素。如果迭代器中没有更多元素,则 next() 方法会引发 StopIteration 异常。

最后,该代码使用 except 语句来处理 StopIteration 异常。当 StopIteration 异常被引发时,该代码会跳出循环。

输入:

1
2
3
4
5

示例2:使用 next() 方法手动遍历迭代器。

# 使用 iter() 函数将列表转换为迭代器。
my_iterator = iter(my_list)# 使用 next() 方法手动遍历列表
while True:try:item = next(my_iterator)print(item)except StopIteration:break

输出:

1
2
3
4
5

3. 自定义迭代器

前面我们使用用 iter() 函数将列表转换为迭代器。当然,也可以创建自定义迭代器来遍历任何类型的数据集。例如,可以创建一个迭代器来遍历一个字符串:

class MyStringIterator:def __init__(self, string):# 将字符串存储为属性self.string = string# 将索引初始化为 0self.index = 0def __iter__(self):# 返回自身以指示它是迭代器return selfdef __next__(self):# 检查是否已到达字符串末尾if self.index < len(self.string):# 获取当前索引处的字符item = self.string[self.index]# 将索引增加 1 以指向下一个字符self.index += 1# 返回字符return itemelse:# 引发 StopIteration 异常以指示迭代结束raise StopIterationmy_string = "Hello, world!"# 使用自定义迭代器遍历字符串
for item in MyStringIterator(my_string):print(item)

输出:

H
e
l
l
o
,w
o
r
l
d
!
关于迭代器,需要记住所有迭代器都是可迭代对象,但并非所有可迭代对象都是迭代器。例如,字符串是可迭代对象,但不是迭代器。

4. 生成器(Generators)

生成器是什么?

生成器(Generators)是一种特殊的迭代器,通过yield 关键字来创建,它可以延迟执行,并逐个生成值

使用生成器表达式:

# 生成器表达式
my_generator = (x for x in range(10))# 遍历生成器
for item in my_generator:print(item)

输出:

0
1
2
3
4
5
6
7
8
9

使用 yield 关键字创建生成器函数

# 生成器函数
def my_generator():for x in range(10):yield x# 遍历生成器
for item in my_generator():print(item)

输出:

0 1 2 3 4 5 6 7 8 9

5. 生成器 vs. 列表推导式

特性生成器列表推导式
返回数据类型生成器列表
内存占用较少较多
计算方式惰性计算立即计算
适用场景数据量较大、需要多次迭代数据量较小、不需要多次迭代

详细说明:

生成器

  • 生成器是一个返回迭代器的函数,只能用于迭代操作。
  • 生成器对象具有惰性求值的特点,即只有需要的时候才生成元素。
  • 可以通过内置函数 next() 或生成器对象的 __next__() 方法获取下一个值。

列表推导式

  • 列表推导式是一种用来创建列表的语法糖。
  • 列表推导式会立即计算并生成整个列表。
  • 列表推导式的语法与生成器表达式相似,但返回的是列表而不是生成器。

选择建议:

  • 如果要多次迭代,建议使用列表推导式。
  • 如果数组很大或者有无穷个元素,建议使用生成器表达式。

6. 生成器的惰性计算(Lazy Evaluation)

惰性计算的优点

  • 节省内存:只生成需要的值,不会占用额外的内存空间。
  • 提高效率:避免了生成不必要的值,提高了计算效率。

生成器表达式的惰性特性

生成器表达式具有惰性特性,即只在需要时才计算值。例如:

# 生成 1 到 10 的平方数
my_generator = (x**2 for x in range(1, 11))# 仅获取前三个平方数
for item in my_generator:print(item)if item >= 9:break

逐步获取生成器的值

可以使用 next() 方法逐步获取生成器的值:

my_generator = (x**2 for x in range(1, 11))# 逐步获取生成器的值
while True:try:item = next(my_generator)print(item)except StopIteration:break

输出:

1
4
9
16
25
36
49
64
81
100

7. 生成器的状态管理

send() 方法:使用 send() 方法向生成器发送值。

def my_generator():x = 0while True:x = yield xprint("Received:", x)# 使用 send() 方法向生成器发送值
my_generator = my_generator()
next(my_generator)  # 初始化生成器
my_generator.send(10)
my_generator.send(20)

输出如下:

Received: 10
Received: 20

throw() 方法:使用 throw() 方法向生成器抛出异常。

def my_generator():try:while True:yieldexcept Exception as e:print("Error:", e)# 使用 throw() 方法向生成器抛出异常
my_generator = my_generator()
next(my_generator)
my_generator.throw(ValueError("Error "))

输出:

Error

close() 方法:使用 close() 方法关闭生成器。

def my_generator():try:while True:yieldfinally:print("Generator closed")# 使用 close() 方法关闭生成器
my_generator = my_generator()
next(my_generator)
my_generator.close()  # 输出:Generator closed

8. 生成器的并发与异步

生成器是一个可以暂停和恢复执行的函数,它会生成一个值并暂停,然后等待下一次调用时再继续执行。这使得它们非常适合处理大量的数据或在异步编程中执行并发操作

使用生成器实现并发

生成器可以与线程一起使用,从而实现一些形式的并发操作。Python 的 concurrent.futures 模块提供了 ThreadPoolExecutor 和 ProcessPoolExecutor,这些可以与生成器一起使用,允许你并发地运行多个生成器函数。

import concurrent.futuresdef my_generator_function(data):for item in data:# 执行一些操作yield processed_itemdef main():data = [1, 2, 3, 4, 5]with concurrent.futures.ThreadPoolExecutor() as executor:results = list(executor.map(my_generator_function, data))print(results)if __name__ == "__main__":main()

这里的 executor.map 函数允许你并发地调用 my_generator_function 函数,并且结果会被收集到一个列表中。

异步生成器和 async/await

异步生成器允许你在生成器函数中使用 await 关键字,这使得你可以等待其他异步操作完成,而不会阻塞整个生成器。

在 Python 3.6 及更高版本中,你可以使用 async def 定义异步生成器函数,使用 yield 语句生成值:

async def async_generator_function(data):for item in data:# 进行一些异步操作yield processed_item

然后你可以使用 async for 循环来遍历异步生成器产生的值:

async def main():async for item in async_generator_function(data):print(item)if __name__ == "__main__":import asynciodata = [1, 2, 3, 4, 5]asyncio.run(main())

这里的 async for 循环允许你在异步函数中迭代异步生成器的值,而不会阻塞事件循环。

总结

关于迭代器和生成器,这里也讲得差不多了,想必大家对迭代器和生成器的概念也有更深入的理解了。那么,大家可以试试敲敲代码,实际运行一番。

欢迎大家和我一起继续学习、记录python的下一个知识点。

如果感觉阅读对您还有些作用,可以评论留言,关注我。谢谢您的阅读!

往期学习:

 
Python安装教程(版本3.8.10)windows10

Linux系统:安装Conda(miniconda)

Conda快速安装的解决方法(Mamba安装)

VSCode安装教程(版本:1.87.0)Windows10

Python基础语法:从入门到精通的必备指南

Python的基本数据类型

Python数据类型间的转换(隐式、显式)

Python基础知识:运算符详解

Python基础知识:数字类型及数学函数详解-

Python字符串操作及方法详解!一篇就搞定!

Python列表及其操作详解,从此不再迷茫!

Python元组(Tuple)深度解析!

Python字典的使用技巧(一篇详解)

Python条件控制深度解析,成为编程必备

Python循环语句全解析(附实战演练)

Python函数高效编程技巧,提升你的代码效率!

Python模块和包全解析,一篇文章就够!

Python lambda(匿名函数),一文详解

Python面向对象编程:合集篇(类、对象、封装、继承和多态)

Python命名空间和作用域,让你的代码逻辑更清晰!

Python正则表达式初学者指南,轻松上手! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/756179.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

bootstrap表格API文档

表格参数&#xff1a; 名称标签类型默认描述-data-toggleString‘table’不用写 JavaScript 直接启用表格。classesdata-classesString‘table table-hover’表格的类名称。默认情况下&#xff0c;表格是有边框的&#xff0c;你可以添加 ‘table-no-bordered’ 来删除表格的边…

Android 12 SystemUI调试

一、调试步骤 在开发过程中&#xff0c;除了可使用AS(Android Studio)开发工具调试源码&#xff0c;还可使用其他开发工具例如VS code&#xff0c;由于篇幅有限&#xff0c;本文只讲如何使用AS调试System UI&#xff0c;如若需要使用Android Studio进行SystemUI的调试工作&…

QCustomPlot-绘制X轴为日期的折线图

主要代码如下&#xff1a; void Widget::InitQLineXDateAddData() {customPlot new QCustomPlot(this);// 创建日期时间类型的刻度生成器QSharedPointer<QCPAxisTickerDateTime> dateTimeTicker(new QCPAxisTickerDateTime);dateTimeTicker->setDateTimeFormat(&quo…

蓝桥杯第642题——跳蚱蜢

题目描述 如下图所示&#xff1a; 有 9 只盘子&#xff0c;排成 1 个圆圈。 其中 8 只盘子内装着 8 只蚱蜢&#xff0c;有一个是空盘。 我们把这些蚱蜢顺时针编号为 1 ~ 8。 每只蚱蜢都可以跳到相邻的空盘中&#xff0c; 也可以再用点力&#xff0c;越过一个相邻的蚱蜢跳到空盘…

数据库学习记录(一)基础语法与单表查询

基础sql语句分类 DDL操作&#xff08;图形化界面&#xff09; 用来定义数据库对象的&#xff0c;例如创建数据库&#xff0c;创建表单 数据库操作 表操作 DML操作&#xff08;掌握&#xff09; 1、insert为添加语句&#xff0c;该语句功能是添加相关数据到表结构中 下面为添…

【爬虫】 突破Cloudflare 5秒盾的艺术:使用Cloudscraper

无心生大用,有物不通神 &#x1f3b5; 闪现吃血王昭君《道德经》 在当今的互联网世界中&#xff0c;保护网站免受恶意访问变得尤为重要。Cloudflare是一种流行的解决方案&#xff0c;提供了多种安全功能&#xff0c;包括一个被广泛称为"5秒盾"(…

【Anaconda】换源常用命令

【Anaconda】换源常用命令 注意换源只需配置清华或中科大或阿里中的任意一个即可&#xff0c;都列出来只是为了备用&#xff0c;方便查找 每创建一个新的虚拟环境&#xff0c;都需要换一次源 查看当前源 conda config --show channels配置清华源 清华源官网 conda config -…

学习笔记 | 微信小程序项目day04

今日学习内容 热门推荐下转页面 热门推荐下转页面 1、定义类型 import type { PageResult, GoodsItem } from ./global/** 热门推荐 */ export type HotResult {/** id信息 */id: string/** 活动图片 */bannerPicture: string/** 活动标题 */title: string/** 子类选项 */…

tensorflow 随机采样

实现随机采样 dataset tf.data.Dataset.from_tensor_slices((x, y)) dataset dataset.shuffle(len(x)).batch(32)train_size, val_size, test_size 0.8, 0.1, 0.1train_dataset dataset.take(int(train_size * len(dataset))) val_dataset dataset.skip(int(train_size *…

开源的OCR工具基本使用:PaddleOCR/Tesseract/CnOCR

前言 因项目需要&#xff0c;调研了一下目前市面上一些开源的OCR工具&#xff0c;支持本地部署&#xff0c;非调用API&#xff0c;主要有PaddleOCR/CnOCR/chinese_lite OCR/EasyOCR/Tesseract/chineseocr/mmocr这几款产品。 本文主要尝试了EasyOCR/CnOCR/Tesseract/PaddleOCR这…

【开源】SpringBoot框架开发不良邮件过滤系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统用户模块2.2 收件箱模块2.3 发件箱模块2.4 垃圾箱模块2.5 回收站模块2.6 邮箱过滤设置模块 三、实体类设计3.1 系统用户3.2 邮件3.3 其他实体 四、系统展示五、核心代码5.1 查询收件箱档案5.2 查询回收站档案5.3 新…

C语言 数组

文章目录 1.一维数组2.二维数组3.冒泡排序4.一维函数的数组名5.二维数组的数组名 1.一维数组 语法形式&#xff1a;type_t arr_name [const_n] 数组是一组相同类型元素的集合 type_t是指数组的元素类型 arr_name是指数组的名称 const_n是一个常量表达式&#xff0c;用来指定数…

mongoDB7.0.6版安装与使用(最新版踩坑记录)

这里写自定义目录标题 0.前言1.MongoDB下载与安装2.启动服务及验证3.命令行访问4.navicat访问5.停止服务 0.前言 本文总结了最近版mongoDB下载安装的过程及简单的应用&#xff0c;整个过程不涉及修改配置文件&#xff0c;甚至不用设置用户名密码也不用登录认证&#xff0c;在进…

HarmonyOS NEXT应用开发—投票动效实现案例

介绍 本示例介绍使用绘制组件中的Polygon组件配合使用显式动画以及borderRadius实现投票pk组件。 效果预览图 使用说明 加载完成后会有一个胶囊块被切割成两个等大的图形来作为投票的两个选项&#xff0c;中间由PK两字分隔开点击左边选项&#xff0c;两个图形会随着选择人数…

2080: [蓝桥杯2023初赛] 飞机降落

题目描述 N 架飞机准备降落到某个只有一条跑道的机场。 其中第 i 架飞机在 Ti 时刻到达机场上空&#xff0c;到达时它的剩余油料还可以继续盘旋 Di 个单位时间。 即它最早可以于 Ti 时刻开始降落&#xff0c;最晚可以于 Ti Di 时刻开始降落。 降落过程需要Li个单位时间。 一架…

Java城管智慧执法管理系统源码带APP

目录 一、系统概述 二、系统开发环境 三、功能模块 四、应用价值 1、提升案件办理效率 2、提升监管效能 3、提升行政执法水平 4、推进行政执法创新 一、系统概述 智慧城管系统是一个基于现代信息技术手段的综合管理平台&#xff0c;旨在通过强化信息获取自动化、监督管…

二分算法详、

二分的概念 二分算法&#xff1a;是用来在一个有序数组中查找一个元素的算法。时间复杂度O&#xff08;log n&#xff09; 二分的二段性 集合中的元素有存在分界线&#xff0c;给定条件可以将集合中的元素分为两部分&#xff0c;一部分满足条件&#xff0c;一部分不满足条件…

官宣!眉州东坡终生认养大熊猫“星星”

2024年03月19日,眉州东坡终生认养大熊猫“星星”签约仪式暨第八届有机川熊猫竹笋节在北京和重庆同时举行。眉州东坡董事长王刚先生、重庆动物园副处长殷毓中先生等嘉宾在重庆共同出席了此次认养仪式,重庆动物园向眉州东坡授予大熊猫终生认养证书,宣布星星正式加入眉州东坡大家庭…

Game of Nodes 16进8

KNIME 还可以用成这样? 是不是有点过分了。 Tableau, PowerBI 同学请绕行&#xff0c;我们讨论的不是同一个东西... 由于 Game of Nodes 没有公开题目&#xff0c;且各个小组赛的题目也是不一样的&#xff0c;在这里我们只能通过拼接图来猜想小组赛题目了。 有的解决方案我甚至…

Android源码阅读 SharedPreferences - 1

目录 前言 正文 SharedPreferences.java PreferenceManager.java ContextImpl.java 前言 由于笔者目前水平限制&#xff0c;表达能力有限&#xff0c;尽请见谅。 SharedPreferences提供了一种轻量级的数据存储方式&#xff0c;允许保存和获取简单的键值对。它适用于保存少…