python 中的生成器

image.png

目录

  • 生成器示例
      • 基本生成器示例
      • 无限序列生成器
      • 使用生成器表达式
      • 实用示例:按行读取大文件
      • 生成器的 `send`、`throw` 和 `close` 方法
  • 生成器和迭代器
      • 迭代器(Iterator)
        • 定义
        • 创建
        • 使用
        • 示例
      • 生成器(Generator)
        • 定义
        • 创建
        • 使用
        • 示例
      • 主要区别和联系
        • 1. 创建方式
        • 2. 代码简洁性
        • 3. 内存效率
        • 4. 使用方式
      • 示例对比
        • 迭代器示例
        • 生成器示例
      • 总结
  • 生成器和列表
      • 1. 定义和存储
      • 2. 内存使用
      • 3. 访问方式
      • 4. 惰性求值(Lazy Evaluation)
      • 5. 可复用性
      • 6. 示例对比
        • 序列示例
        • 生成器示例
      • 总结
  • 生成器的应用总结

在 Python 中,生成器(Generator)是一种特殊类型的迭代器,允许你在迭代过程中逐步生成值,而不是一次性生成所有值。生成器的创建通常通过包含 yield 关键字的函数实现。当函数包含 yield 时,该函数会返回一个生成器对象。
image.png

生成器的主要优点包括:

  1. 延迟求值(Lazy Evaluation):生成器在需要值的时候才生成值,这样可以节省内存。
  2. 流式处理(Stream Processing):适用于处理大型数据集或无限序列,因为它们不会将所有值一次性加载到内存中。
  3. 简洁的代码:生成器可以使代码更简洁和可读,特别是处理复杂迭代逻辑时。
    image.png

生成器示例

下面是一些使用生成器的示例:

image.png

基本生成器示例

一个简单的生成器函数,它生成从 0 到 n 的数字:

def simple_generator(n):
    for i in range(n):
        yield i

gen = simple_generator(5)
for value in gen:
    print(value)

输出:

0
1
2
3
4

无限序列生成器

生成器可以用于创建无限序列,例如生成斐波那契数列:

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fib_gen = fibonacci()
for _ in range(10):
    print(next(fib_gen))

输出:

0
1
1
2
3
5
8
13
21
34

使用生成器表达式

生成器表达式是生成器的简洁形式,类似于列表解析(List Comprehensions),但它们使用圆括号 () 而不是方括号 []。例如:

gen_exp = (x * x for x in range(10))
for value in gen_exp:
    print(value)

输出:

0
1
4
9
16
25
36
49
64
81

实用示例:按行读取大文件

生成器可以用于按行读取大文件而不占用过多内存:

def read_large_file(file_path):
    with open(file_path, 'r') as file:
        while line := file.readline():
            yield line.strip()

file_gen = read_large_file('large_file.txt')
for line in file_gen:
    print(line)

生成器的 sendthrowclose 方法

image.png

生成器对象有三个额外的方法:

  • send(value):恢复生成器,并向生成器提供一个值,该值会成为生成器中 yield 表达式的返回值。
  • throw(type, value=None, traceback=None):在生成器中抛出一个异常。
  • close():停止生成器。

示例:

def generator_with_send():
    while True:
        value = (yield)
        print(f'Received: {value}')

gen = generator_with_send()
next(gen)  # 预激生成器
gen.send('Hello')
gen.send('World')
gen.close()

输出:

Received: Hello
Received: World

使用生成器可以编写高效、易读的代码,特别是在处理需要逐步生成数据的场景时。

生成器和迭代器

image.png

生成器和迭代器在 Python 中都是用于迭代的对象,但它们之间有一些显著的区别和联系。下面是生成器和迭代器的详细比较:

迭代器(Iterator)

定义
  • 迭代器是一个实现了 __iter__()__next__() 方法的对象。
  • 任何实现了这些方法的对象都可以用于迭代。
创建
  • 迭代器通常通过实现这两个方法来创建。
  • 也可以使用内置的 iter() 函数从一个可迭代对象(如列表或元组)创建迭代器。
使用
  • 通过 next() 函数获取下一个元素。
  • 当没有更多元素时,next() 会抛出 StopIteration 异常。
示例
# 创建一个迭代器
class MyIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.current >= self.end:
            raise StopIteration
        else:
            self.current += 1
            return self.current - 1

it = MyIterator(1, 5)
for num in it:
    print(num)

# 使用内置的 iter() 函数
lst = [1, 2, 3, 4]
it = iter(lst)
print(next(it))  # 输出: 1
print(next(it))  # 输出: 2

生成器(Generator)

定义
  • 生成器是一个特殊的迭代器,通过函数来定义,使用 yield 关键字生成值。
  • 每次调用生成器函数时,生成器函数返回一个生成器对象,这个对象实现了迭代器协议。
创建
  • 通过包含 yield 关键字的函数创建。
  • 生成器表达式也可以用于创建生成器,类似于列表解析(List Comprehensions)。
使用
  • 通过 next() 函数获取下一个元素,或在 for 循环中使用。
  • 当没有更多元素时,生成器自动抛出 StopIteration 异常。
示例
# 生成器函数
def my_generator():
    for i in range(1, 5):
        yield i

gen = my_generator()
for num in gen:
    print(num)

# 生成器表达式
gen_exp = (x * x for x in range(5))
for num in gen_exp:
    print(num)

主要区别和联系

1. 创建方式
  • 迭代器:通过实现 __iter__()__next__() 方法的类创建。
  • 生成器:通过函数定义,使用 yield 关键字。
2. 代码简洁性
  • 迭代器:创建迭代器需要定义一个类并实现两个方法。
  • 生成器:生成器函数更简洁,只需定义一个函数并使用 yield
3. 内存效率
  • 迭代器:通常用于较小的数据集合,因为它们需要预先定义数据集合。
  • 生成器:适用于大数据集合或无限数据流,因为它们是按需生成数据。
4. 使用方式
  • 迭代器:需要显式调用 next() 获取下一个元素。
  • 生成器:可以像普通函数一样调用,并在 for 循环中直接使用。

示例对比

迭代器示例
class Counter:
    def __init__(self, low, high):
        self.current = low
        self.high = high

    def __iter__(self):
        return self

    def __next__(self):
        if self.current > self.high:
            raise StopIteration
        else:
            self.current += 1
            return self.current - 1

counter = Counter(1, 5)
for num in counter:
    print(num)
生成器示例
def counter(low, high):
    current = low
    while current <= high:
        yield current
        current += 1

for num in counter(1, 5):
    print(num)

总结

  • 生成器是迭代器的一种,提供了更简洁的语法和更高的内存效率,适合处理大数据或无限序列。
  • 迭代器提供了更灵活的实现方式,适合需要自定义迭代行为的场景。

生成器和列表

image.png

生成器和序列在 Python 中有显著的区别。下面从几个方面来详细比较它们:

1. 定义和存储

  • 序列(Sequence)

    • 序列是一种容器数据类型,包含了一系列有序的元素,如列表(list)、元组(tuple)、字符串(string)等。
    • 序列中的元素是预先存储在内存中的,可以通过索引直接访问。
  • 生成器(Generator)

    • 生成器是一种特殊的迭代器,用于逐步生成元素。生成器函数使用 yield 关键字来返回一个生成器对象。
    • 生成器在运行时逐步生成元素,并不会将所有元素一次性存储在内存中。

2. 内存使用

  • 序列:由于序列会将所有元素存储在内存中,所以在处理大数据集时可能会占用大量内存。
  • 生成器:生成器按需生成元素,仅在需要时生成下一个元素,因而在处理大数据集时非常节省内存。

3. 访问方式

  • 序列:支持通过索引访问元素,并且支持切片操作。例如 lst[0]lst[1:3]
  • 生成器:不支持索引访问和切片操作。只能通过迭代器接口(如 for 循环或 next() 函数)逐个获取元素。

4. 惰性求值(Lazy Evaluation)

  • 序列:所有元素在创建时就被立即计算并存储。
  • 生成器:元素是按需计算的,只有在访问时才会生成对应的值。这种惰性求值方式可以提高效率,尤其在处理潜在的无限序列或大数据集时。

5. 可复用性

  • 序列:可以多次遍历。例如,你可以多次使用 for 循环遍历列表。
  • 生成器:只能遍历一次。一旦生成器到达末尾,再次遍历时需要重新创建生成器对象。

6. 示例对比

序列示例
# 使用列表(序列)
sequence = [1, 2, 3, 4, 5]
for item in sequence:
    print(item)

# 可以通过索引访问
print(sequence[2])

# 可以多次遍历
for item in sequence:
    print(item)
生成器示例
# 使用生成器
def simple_generator():
    for i in range(1, 6):
        yield i

gen = simple_generator()

# 逐个获取生成器的值
for item in gen:
    print(item)

# 再次遍历需要重新创建生成器
gen = simple_generator()
for item in gen:
    print(item)

# 不能通过索引访问
try:
    print(gen[2])
except TypeError as e:
    print(e)  # 'generator' object is not subscriptable

总结

  • 序列适用于需要频繁随机访问元素和多次遍历的场景。
  • 生成器适用于处理大型数据集或无限序列,以及按需生成数据的场景。生成器在内存效率和惰性求值方面有显著优势。

生成器的应用总结

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

政策公告与提醒

自 2024 年 4 月 3 日起,您将至少有 30 天的时间来更新应用,使其符合下方所述的政策变更。 我们将推出“儿童安全标准”政策,规定社交应用和约会交友应用必须遵循特定标准,并在 Play 管理中心内以自行认证的形式证明合规后才能发布。 为了提高健康相关应用在 Google Play…

grpc-go服务端接口添加

【1】新建一个目录whgserviceproto&#xff0c;目录下新建一个proto包&#xff1a;whgserviceproto.proto &#xff08;注意目录和包名称保持一致&#xff09; //协议为proto3 syntax "proto3"; // 指定生成的Go代码在你项目中的导入路径 option go_package"…

taoCMS v3.0.2 任意文件读取漏洞(CVE-2022-23316)

前言 CVE-2022-23316 是一个影响 taoCMS v3.0.2 的漏洞。这个漏洞允许攻击者通过 admin.php?actionfile&ctrldownload&path../../1.txt 的路径读取任意文件。攻击者可以利用该漏洞读取服务器上的任何文件&#xff0c;只要他们知道文件的路径​ (OpenCVE)​​ (Tenabl…

2024年最新运维面试题(附答案)

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 公众号&#xff1a;网络豆云计算学堂 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a; 网络豆的主页​​​​​ 一&#xff0e;选择题 1.HTTP协议默认使用哪个端口…

【Linux】什么是进程间通信?方式有哪些?本质理解?

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

【web前端HTML+CSS+JS】--- HTML学习笔记01

学习链接&#xff1a;黑马程序员pink老师前端入门教程&#xff0c;零基础必看的h5(html5)css3移动端前端视频教程_哔哩哔哩_bilibili 学习文档&#xff1a; Web 开发技术 | MDN (mozilla.org) 一、前后端工作流程 WEB模型&#xff1a;前端用于采集和展示信息&#xff0c;中…

maven的卸载与安装

卸载 1.找到当前的maven路径:使用 mvn -v 查看当前maven的安装目录在哪 2.删掉 sudo rm -rf [maven的路径] 3.再次输入 mvn -v 查看是否删除成功 安装 1.下载maven安装包 https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/ 注意&#xff1a;maven版本请使用3.…

AcWing 1550:完全二叉搜索树

【题目来源】https://www.acwing.com/problem/content/1552/【题目描述】二叉搜索树 (BST) 递归定义为具有以下属性的二叉树&#xff1a; &#xff08;1&#xff09;若它的左子树不空&#xff0c;则左子树上所有结点的值均小于它的根结点的值 &#xff08;2&#xff09;若它的右…

银行信用卡风险大数据分析与挖掘2024

银行信用卡风险大数据分析与挖掘 使用excel数据挖掘功能完成 一、信用卡客户信用等级影响因素分析与挖掘 基于客户信用记录表 1. 数据预处理 浏览数据 客户等级占比&#xff0c;其中优质客户占比较少&#xff0c;风险客户很多&#xff0c;分析影响客户信用等级的原因 年…

Hugging face Transformers(2)—— Pipeline

Hugging Face 是一家在 NLP 和 AI 领域具有重要影响力的科技公司&#xff0c;他们的开源工具和社区建设为NLP研究和开发提供了强大的支持。它们拥有当前最活跃、最受关注、影响力最大的 NLP 社区&#xff0c;最新最强的 NLP 模型大多在这里发布和开源。该社区也提供了丰富的教程…

一维前缀和的实现

这是C算法基础-基础算法专栏的第十一篇文章&#xff0c;专栏详情请见此处。 引入 我们用朴素做法求一维数组的区间和时&#xff0c;一般是从前向后循环累加&#xff0c;它的时间复杂度为&#xff0c;当求区间和的次数过多&#xff0c;则会有超时的可能&#xff0c;那有没有时间…

web零碎知识2

不知道我的这个axios的包导进去没。 找一下关键词&#xff1a; http请求协议&#xff1a;就是进行交互式的格式 需要定义好 这个式一发一收短连接 而且没有记忆 这个分为三个部分 第一个式请求行&#xff0c;第二个就是请求头 第三个就是请求体 以get方式进行请求的失手请求…

SpringBoot新手快速入门系列教程四:创建第一个SringBoot的API

首先我们用IDEA新建一个项目&#xff0c;请将这些关键位置按照我的设置设置一下 接下来我将要带着你一步一步创建一个Get请求和Post请求&#xff0c;通过客户端请求的参数&#xff0c;以json格式返回该参数{“message”:"Hello"} 1,先在IDE左上角把这里改为文件模式…

3101.力扣每日一题7/6 Java(接近100%解法)

博客主页&#xff1a;音符犹如代码系列专栏&#xff1a;算法练习关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 目录 思路 解题方法 时间复杂度 空间复杂度 Code 思路 主要是基于对…

connect to github中personal access token生成token方法

一、问题 执行git push时弹出以下提示框 二、解决方法 去github官网生成Token&#xff0c;步骤如下 选择要授予此 令牌token 的 范围 或 权限 要使用 token 从命令行访问仓库&#xff0c;请选择 repo 。 要使用 token 从命令行删除仓库&#xff0c;请选择 delete_repo 其他根…

06-6.4.4 拓扑排序

&#x1f44b; Hi, I’m Beast Cheng &#x1f440; I’m interested in photography, hiking, landscape… &#x1f331; I’m currently learning python, javascript, kotlin… &#x1f4eb; How to reach me --> 458290771qq.com 喜欢《数据结构》部分笔记的小伙伴可以…

搜索广告召回技术在美团的实践

内容整理自美团技术沙龙第81期《美团在广告算法领域的探索及实践》&#xff08;B站视频&#xff09;。本文首先介绍了美团搜索广告的三个阶段&#xff1a;多策略关键词挖掘、分层召回体系、生成式召回&#xff1b;然后重点介绍了生成式关键词召回、多模态生成式向量召回、生成式…

计算机网络之令牌总线

上文内容&#xff1a;什么是以太网 1.令牌总线工作原理 在总线的基础上&#xff0c;通过在网络结点之间有序地传递令牌来分配各结点对共享型总线的访问权利&#xff0c;形成闭合的逻辑环路。 完全采用半双工的操作方式&#xff0c;只有获得令牌的结点才能发送信息&#xff…

第1章 项目背景(学成在线),项目介绍,环境搭建

1.项目背景 1.1 在线教育市场环境 以下内容摘自https://report.iresearch.cn/content/2021/01/358854.shtml 在线教育行业是一个有着极强的广度和深度的行业&#xff0c;从校内到校外&#xff1b;从早幼教到职业培训&#xff1b;从教育工具到全信息化平台等等。 2020年的新…

NVIDIA RTX Remix开源 让AI驱动的经典游戏重制复兴

游戏开发商往往会让激动的粉丝们在游戏发布后等待数年&#xff0c;以获得他们喜爱的游戏的重制版。不过&#xff0c;这个问题可能很快就会成为过去。NVIDIA 宣布其 RTX Remix 工具包将开放源代码&#xff0c;这将为钟情于经典游戏的玩家带来惊喜。 RTX Remix 是 NVIDIA 的修改套…