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 igen = simple_generator(5)
for value in gen:print(value)

输出:

0
1
2
3
4

无限序列生成器

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

def fibonacci():a, b = 0, 1while True:yield aa, b = b, a + bfib_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 = startself.end = enddef __iter__(self):return selfdef __next__(self):if self.current >= self.end:raise StopIterationelse:self.current += 1return self.current - 1it = 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 igen = 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 = lowself.high = highdef __iter__(self):return selfdef __next__(self):if self.current > self.high:raise StopIterationelse:self.current += 1return self.current - 1counter = Counter(1, 5)
for num in counter:print(num)
生成器示例
def counter(low, high):current = lowwhile current <= high:yield currentcurrent += 1for 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 igen = 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

总结

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

生成器的应用总结

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

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

相关文章

【python学习】自定义函数的一些高级用法-2

8. 生成器函数 生成器函数允许你定义一个可以“记住”其当前执行状态的函数&#xff0c;并在下次调用时从上次离开的位置继续执行。生成器函数使用yield关键字而不是return。 def simple_generator(): yield 1 yield 2 yield 3 gen simple_generator() print(next(gen)) # …

隐私计算实训营第二期第十课:基于SPU机器学习建模实践

隐私计算实训营第二期-第十课 第十课&#xff1a;基于SPU机器学习建模实践1 隐私保护机器学习背景1.1 机器学习中隐私保护的需求1.2 PPML提供的技术解决方案 2 SPU架构2.1 SPU前端2.2 SPU编译器2.3 SPU运行时2.4 SPU目标 3 密态训练与推理3.1 四个基本问题3.2 解决数据来源问题…

全新升级!中央集中式架构功能测试为新车型保驾护航

“软件定义汽车”新时代下&#xff0c;整车电气电气架构向中央-区域集中式发展已成为行业共识&#xff0c;车型架构的变革带来更复杂的整车功能定义、更多的新技术的应用&#xff08;如SOA服务化、智能配电等&#xff09;和更短的车型研发周期&#xff0c;对整车和新产品研发的…

OkHttp的源码解读1

介绍 OkHttp 是 Square 公司开源的一款高效的 HTTP 客户端&#xff0c;用于与服务器进行 HTTP 请求和响应。它具有高效的连接池、透明的 GZIP 压缩和响应缓存等功能&#xff0c;是 Android 开发中广泛使用的网络库。 本文将详细解读 OkHttp 的源码&#xff0c;包括其主要组件…

Qt实现手动切换多种布局

引言 之前写了一个手动切换多个布局的程序&#xff0c;下面来记录一下。 程序运行效果如下&#xff1a; 示例 需求 通过点击程序界面上不同的布局按钮&#xff0c;使主工作区呈现出不同的页面布局&#xff0c;多个布局之间可以通过点击不同布局按钮切换。支持的最多的窗口…

如何使用 AppML

如何使用 AppML AppML(Application Markup Language)是一种轻量级的标记语言,旨在简化Web应用的创建和部署过程。它允许开发者通过XML或JSON格式的配置文件来定义应用的结构和行为,从而实现快速开发和灵活扩展。AppML特别适用于构建数据驱动的企业级应用,它可以与各种后端…

pytorch跑手写体实验

目录 1、环境条件 2、代码实现 3、总结 1、环境条件 pycharm编译器pytorch依赖matplotlib依赖numpy依赖等等 2、代码实现 import torch import torch.nn as nn import torch.optim as optim import torchvision import torchvision.transforms as transforms import matpl…

burpsuite 设置监听窗口 火狐利用插件快速切换代理状态

一、修改burpsuite监听端口 1、首先打开burpsuite&#xff0c;点击Proxy下的Options选项&#xff1a; 2、可以看到默认的监听端口为8080&#xff0c;首先选中我们想要修改的监听&#xff0c;点击Edit进行编辑 3、将端口改为9876&#xff0c;并保存 4、可以看到监听端口修改成功…

typescript学习回顾(五)

今天来分享一下ts的泛型&#xff0c;最后来做一个练习 泛型 有时候&#xff0c;我们在书写某些函数的时候&#xff0c;会丢失一些类型信息&#xff0c;比如我下面有一个例子&#xff0c;我想提取一个数组的某个索引之前的所有数据 function getArraySomeData(newArr, n:numb…

JVM原理(十):JVM虚拟机调优分析与实战

1. 大内存硬件上的程序部署策略 这是笔者很久之前处理过的一个案例&#xff0c;但今天仍然具有代表性。一个15万PV/日左右的在线文档类型网站最近更换了硬件系统&#xff0c;服务器的硬件为四路志强处理器、16GB物理内存&#xff0c;操作系统为64位CentOS5.4&#xff0c;Resin…

js数组方法归纳——concat、join、reverse

1、concat( ) 用途&#xff1a;可以连接两个或多个数组&#xff0c;并将新的数组返回该方法不会对原数组产生影响 var arr ["孙悟空","猪八戒","沙和尚"];var arr2 ["白骨精","玉兔精","蜘蛛精"];var arr3 [&…

Vue Router的深度解析

引言 在现代Web应用开发中&#xff0c;客户端路由已成为实现流畅用户体验的关键技术。与传统的服务器端路由不同&#xff0c;客户端路由通过JavaScript在浏览器中控制页面内容的更新&#xff0c;避免了页面的全量刷新。Vue Router作为Vue.js官方的路由解决方案&#xff0c;以其…

阿里云centos 取消硬盘挂载并重建数据盘信息再次挂载

一、取消挂载 umount [挂载点或设备] 如果要取消挂载/dev/sdb1分区&#xff0c;可以使用以下命令&#xff1a; umount /dev/sdb1 如果要取消挂载在/mnt/mydisk的挂载点&#xff0c;可以使用以下命令&#xff1a; umount /mnt/mydisk 如果设备正忙&#xff0c;无法立即取消…

【Spring Boot】简单了解spring boot支持的三种服务器

Tomcat 概述&#xff1a;Tomcat 是 Apache 软件基金会&#xff08;Apache Software Foundation&#xff09;的 Jakarta EE 项目中的一个核心项目&#xff0c;由 Apache、Sun 和其他一些公司及个人共同开发而成。它作为 Java Servlet、JSP、JavaServer Pages Expression Languag…

系统安全及应用(命令)

目录 一、账号安全控制 1.1 系统账号清理 1.2 密码安全控制 1.3 历史记录控制 1.4 终端自动注销 二、系统引导和登陆控制 2.1 限制su命令用户 2.2 PAM安全认证 示例一&#xff1a;通过pam 模块来防止暴力破解ssh 2.3 sudo机制提升权限 2.3.1 sudo命令&#xff08;ro…

Java的日期类常用方法

Java_Date 第一代日期类 获取当前时间 Date date new Date(); System.out.printf("当前时间" date); 格式化时间信息 SimpleDateFormat simpleDateFormat new SimpleDateFormat("yyyy-mm-dd hh:mm:ss E); System.out.printf("格式化后时间" si…

【windows|012】光猫、路由器、交换机详解

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 ​ &#x1f3c5;阿里云ACE认证高级工程师 ​ &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社…

windows USB 驱动开发-URB结构

通用串行总线 (USB) 客户端驱动程序无法直接与其设备通信。 相反&#xff0c;客户端驱动程序会创建请求并将其提交到 USB 驱动程序堆栈进行处理。 在每个请求中&#xff0c;客户端驱动程序提供一个可变长度的数据结构&#xff0c;称为 USB 请求块 (URB) &#xff0c;URB 结构描…

ctfshow-web入门-命令执行(web75-web77)

目录 1、web75 2、web76 3、web77 1、web75 使用 glob 协议绕过 open_basedir&#xff0c;读取根目录下的文件&#xff0c;payload&#xff1a; c?><?php $anew DirectoryIterator("glob:///*"); foreach($a as $f) {echo($f->__toString(). ); } ex…

读书笔记-Java并发编程的艺术-第3章(Java内存模型)-第9节(Java内存模型综述)

3.9 Java内存模型综述 前面对Java内存模型的基础知识和内存模型的具体实现进行了说明。下面对Java内存模型的相关知识做一个总结。 3.9.1 处理器的内存模型 顺序一致性内存模型是一个理论参考模型&#xff0c;JMM和处理器内存模型在设计时通常会以顺序一致性内存模型为参照。…