Python基础:生成器(Generators)和生成器表达式(Generator Expressions)详解

news2024/12/24 11:45:03

在这里插入图片描述

  生成器Generators)和 生成器表达式Generator Expressions)是 Python 中用于处理迭代器和序列数据的强大工具。它们允许你按需生成值,而不是一次性生成所有值,从而节省内存和提高性能。

1. 生成器(Generators

  生成器 是一个用于创建迭代器的简单而强大的工具。 它们的写法类似于标准的函数,但当它们要返回数据时(返回一个generator iterator的函数)会使用 yield语句。 每次在生成器上调用 next() 时,它会从上次离开的位置恢复执行(它会记住上次执行语句时的所有数据值)。

1.1 语法

def my_generator():
    yield 1
    yield 2
    yield 3

  生成器使用函数中的yield 语句来生成值,每次调用生成器的__next__() 方法时,函数会执行到 yield,返回值并暂停,下一次调用会从上次暂停的地方继续执行。
  1)yield: 返回一个值,并暂停生成器的执行。
  2)__next__(): 获取生成器的下一个值。
  3)生成器可以使用for 循环来遍历。

1.2 应用场景

  1)处理大数据集: 生成器适合处理大量数据,因为它们一次只生成一个值,而不是一次性生成所有值。
  2)无限序列: 适用于表示无限序列,例如斐波那契数列。
  3)懒加载: 用于按需加载大文件中的数据。
  4)状态机: 生成器可以用于实现状态机,处理一系列有序事件。
  5)异步编程: 在异步编程中,生成器可以用于实现协程。

1.3 简单示例

  按照指定的模式生成一系列字符串

def pattern_generator(n):
    for i in range(1,n+1):
        yield '  A  ' * i

# 使用生成器生成一系列字符串
pattern_gen = pattern_generator(5)
for pattern in pattern_gen:
    print(pattern)

在这里插入图片描述

1.4 应用场景示例

1.4.1 处理大数据集

"""
    1)处理大数据集
"""
def read_large_file(file_path):
    with open(file_path, 'r') as file:
        for line in file:
            yield line

# 使用生成器遍历大文件
for data in read_large_file('large_data.txt'):
    process_data(data)

1.4.2 无限序列

"""
    无限序列
    实现斐波那契数列
"""
def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

# 使用生成器获取前 n 个斐波那契数
gen = fibonacci()
fibonacci_values = [next(gen) for _ in range(10)]
print(fibonacci_values)

1.4.3 懒加载

"""
    懒加载-读取数据库记录
"""
def lazy_load_records_from_database(query):
    # Simulating database query
    records = query.execute()
    for record in records:
        yield record

# 使用生成器按需加载数据库记录
query_result = lazy_load_records_from_database(my_query)
for record in query_result:
    process_record(record)

1.4.4 状态机

"""
    状态机
"""
def simple_state_machine():
    state = "start"
    while True:
        if state == "start":
            yield "Processing Start"
            state = "middle"
        elif state == "middle":
            yield "Processing Middle"
            state = "end"
        else:
            yield "Processing End"
            state = "start"

# 使用生成器实现状态机
state_machine = simple_state_machine()
for _ in range(3):
    print(next(state_machine))

1.4.5 异步编程

"""
    异步编程-协程
"""
def simple_coroutine():
    result = yield "Start Coroutine"
    yield f"Received: {result}"

# 使用生成器作为简单的协程
coroutine = simple_coroutine()
print(next(coroutine))  # Start Coroutine
print(coroutine.send("Data"))  # Received: Data

2. 生成器表达式(Generator Expressions)

2.1 语法

  某些简单的生成器可以写成简洁的表达式代码,所用语法类似列表推导式,但外层为 圆括号 而非方括号。 这种表达式被设计用于生成器将立即被外层函数所使用的情况。 生成器表达式相比完整的生成器更紧凑但较不灵活,相比等效的列表推导式则更为节省内存。

gen_expr = (x for x in range(5))

  与生成器类似,使用 __next__() 方法获取下一个值。
  也可以通过for 循环来遍历。

2.2 应用场景

  1)列表筛选: 生成器表达式可以用于按条件筛选列表中的元素。
  2)简单转换: 适用于对序列进行简单的转换操作。
  3)迭代: 用于按需生成值进行迭代。
  4)过滤: 通过生成器表达式筛选或过滤元素。
  5)字典生成: 用于生成字典中的值。

2.3 简单示例

  使用生成器表达式生成一个包含偶数的生成器

sum(i*i for i in range(10))                 # sum of squares

xvec = [10, 20, 30]
yvec = [7, 5, 3]
sum(x*y for x,y in zip(xvec, yvec))     # dot product

unique_words = set(word for line in page  for word in line.split())

valedictorian = max((student.gpa, student.name) for student in graduates)

data = 'golf'
list(data[i] for i in range(len(data)-1, -1, -1))
# 生成器表达式示例:生成包含偶数的生成器
even_numbers_generator = (x for x in range(10) if x % 2 == 0)

# 使用生成器迭代
for number in even_numbers_generator:
    print(number)

2.4 应用场景示例

2.4.1 列表筛选

"""
    列表筛选
"""
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 使用生成器表达式筛选出偶数
even_numbers = (x for x in numbers if x % 2 == 0)
print(list(even_numbers))

在这里插入图片描述

2.4.2 简单转换

"""
    简单转换
"""
original_list = [1, 2, 3, 4, 5]

# 使用生成器表达式将每个元素平方
squared_values = (x**2 for x in original_list)
print(list(squared_values))

在这里插入图片描述

2.4.3 迭代

"""
    迭代
"""
words = ["apple", "banana", "cherry"]

# 使用生成器表达式将每个单词转换为大写
uppercase_words = (word.upper() for word in words)
print(list(uppercase_words))

在这里插入图片描述

2.4.4 过滤

"""
    过滤
"""
data = [10, -2, 8, -7, 4, -1]

# 使用生成器表达式过滤出正数
positive_numbers = (x for x in data if x > 0)
print(list(positive_numbers))

在这里插入图片描述

2.4.5 字典生成

"""
    字典生成
"""
keys = ['a', 'b', 'c']
values = [1, 2, 3]

# 使用生成器表达式创建字典
dictionary = {k: v for k, v in zip(keys, values)}
print(dictionary)

在这里插入图片描述

3. 生成器表达式与普通函数不同点

  返回(生成)一个迭代器对象。你无需担心显式地创建此迭代器对象,yield关键字为你做了这个工作。
  必须包含至少一个yield语句。如果需要,它可能包括多个yield关键字。
  内部实现迭代器协议(iter()next()方法)。
  自动保存局部变量及其状态。
  在yield关键字处暂停执行,并将控制权传递给调用者。
  在迭代器流没有返回值时自动引发StopIteration异常。

4. 生成器的优点

  生成器在许多方面都具有显著的优势,特别是在内存效率、延迟计算、处理无限流、易实现和可读性等方面。
  1)内存效率(逐次生成)
  生成器一次只生成一个值,而不是一次性生成所有值。这意味着在处理大量数据时,生成器可以显著节省内存,因为它们不需要在内存中存储整个序列。
  2)延迟计算(按需生成)
  生成器在需要时生成值,而不是预先生成整个序列。这种延迟计算的方式使得在处理大数据集或无限序列时能够更加高效。
  3)处理无限流(适用于无限序列)
  生成器非常适合处理无限序列,例如斐波那契数列。因为它们是按需生成的,所以可以有效地处理无限流而不会耗尽内存。
  4)易实现
  生成器的语法相对简单,只需使用 yield 关键字即可。这使得实现生成器相对容易,不需要复杂的迭代器或序列处理代码。
  5)可读性
  生成器允许将代码逻辑分解为可读的小块,每个块生成一个值。这提高了代码的可读性,尤其是在处理复杂的数据流时。

5. 参考

  官网:https://docs.python.org/zh-cn/3/tutorial/classes.html#generators
     https://docs.python.org/zh-cn/3/tutorial/classes.html#generator-expressions

在这里插入图片描述

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

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

相关文章

前缀和——724. 寻找数组的中心下标

文章目录 🍓1. 题目🫒2. 算法原理🦄解法一:暴力枚举🦄解法二:前缀和 🥔3. 代码实现 🍓1. 题目 题目链接:724. 寻找数组的中心下标 - 力扣(LeetCode&#xff0…

【一文搞定】在Docker中搭建centos7远程桌面环境(Xfce、Gnome两种方式)

目录 前言一、基于GNOME构建远程桌面二、基于Xfce构建远程桌面(轻量级) 前言 本文提供两种安装方式,均自己测试过,最后还是选择了Xfce,因为它比较轻量级,占用资源较少。大家也可以都试试,比较感…

idea 26 个天花板技巧

1、 查看代码历史版本;2、 调整idea的虚拟内存:;3、 idea设置成eclipse的快捷键;4、 设置提示词忽略大小写;5、 关闭代码检查;6、 设置文档注释模板;7、 显示方法分隔符;8、 设置多行…

【大神支招】3步,打造一张BI报表

随着BI报表的高效直观、灵活分析的特点越来越被大家所熟知,很多BI零基础的用户可积极尝试制作BI报表,以达到灵活自助分析、高效智能分析的效果。那么BI报表零基础的小白们该怎么做BI报表,才能又快又好地做出来? 大神支招&#xf…

Authing 入选《 2023 年央国企信创应用与实践研究报告》优秀服务商

11 月 21 日,Authing 身份云作为国内唯一事件驱动云原生身份平台入选《 2023 年央国企信创应用与实践研究报告》优秀服务商,该报告由第一新声研究院合伙人、Gartner 前高管合伙人/副总裁李长华牵头指导,第一新声创始人兼 CEO 组织&#xff0c…

畅捷通T6 客户端登录提示 运行时错误 372 加载控件cfloatmenu失败

客户单win10电脑, T6版本是 V7.1 不知道操作了什么每个电脑提示 运行时错误372: 从加载控件CFloatMenu失败。您的版本可能已过期。确认您使用的控件版本是同您的应用程序一起提供的。 ******* 解决办法: 找个其他电脑复制mscomctl.ocx 到操作系统目录里面注册一下,即可. …

蓝桥杯物联网竞赛_STM32L071_2_继电器控制

CubeMX配置: Function.c及Function.h: #include "Function.h" #include "gpio.h" void Function_LD5_ON(void){HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_RESET); }void Function_LD5_OFF(void){HAL_GPIO_WritePin(LD5_…

【Unity】 UGUI的PhysicsRaycaster (物理射线检测)组件的介绍及使用

1. 什么是PhysicsRaycaster组件? PhysicsRaycaster是Unity UGUI中的一个组件,用于在UI元素上进行物理射线检测。它可以检测鼠标或触摸事件是否发生在UI元素上,并将事件传递给相应的UI元素。 2. PhysicsRaycaster的工作原理 PhysicsRaycast…

便携式心电图机方案_基于MT6735平台的手持心电图机

便携式心电图机具备体积小、易携带、兼容12导模式的特点,通过工频滤波、基线滤波和肌电滤波等处理,能够获得更精准的心电图谱。该设备可以与医院信息系统(HIS)相连接,实现患者信息的共享。采集的心电数据可以通过无线方式发送到心电判读平台&…

Python函数式编程:让你的代码更优雅更简洁

概要 函数式编程(Functional Programming)是一种编程范式,它将计算视为函数的求值,并且避免使用可变状态和循环。 函数式编程强调的是函数的计算,而不是它的副作用。 在函数式编程中,函数是第一类公民&a…

postgresql数据库中update使用的坑

简介 在数据库中进行增删改查比较常见,经常会用到update的使用。但是在近期发现update在oracle和postgresql使用却有一些隐形区别,oracle 在执行update语句的时候set 后面必须跟着1对1的数据关联而postgresql数据库却可以一对多,这就导致数据…

springboot使用redis缓存乱码(key或者 value 乱码)一招解决

如果查看redis中的值是这样 创建一个配置类就可以解决 package com.deka.config;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; i…

2024年的云趋势:云计算的前景如何?

本文讨论了2024年云计算的发展趋势。 适应复杂的生态系统、提供实时功能、优先考虑安全性和确保可持续性的需求正在引领云计算之船。多样化的工作负载允许探索通用的公共云基础设施范例之外的选项。由于需要降低成本、提高灵活性和降低风险,混合云和多云系统越来越受…

C++中的map和set的使用

C中的map详解 关联式容器键值对树形结构的关联式容器set的使用1. set的模板参数列表2. set的构造3. set的迭代器4. set的容量5. set修改操作6. set的使用举例 map1. map的简介2. map的模板参数说明3. map的构造4. map的迭代器5. map的容量与元素访问6. map的元素修改 multimap和…

机器学习之危险品车辆目标检测

危险品的运输涉及从离开仓库到由车辆运输到目的地的风险。监控事故、车辆运动动态以及车辆通过特定区域的频率对于监督车辆运输危险品的过程至关重要。 在线工具推荐: 三维数字孪生场景工具 - GLTF/GLB在线编辑器 - Three.js AI自动纹理化开发 - YOLO 虚幻合成数…

js实现获取原生form表单的数据序列化表单以及将数组转化为一个对象obj,将数组中的内容作为对象的key转化为对象,对应的值转换为对象对应的值

1.需求场景 哈喽 大家好啊,今天遇到一个场景, js实现获取原生form表单的数据序列化表单以及将数组转化为一个对象obj,将数组中的内容作为对象的key转化为对象,对应的值转换为对象对应的值 数组对象中某个属性的值,转…

开店必看!又有新变化?一文读懂2024亚马逊卖家入驻要求和流程

亚马逊2024年新卖家入驻正在火热进行中,想加入亚马逊卖家行列的小伙伴们准备好了吗?9月20日,亚马逊官方宣布2024年新卖家入驻正式开启,又一年招商季来临,东哥还了解到2024年亚马逊卖家注册要求有了一点新变化&#xff…

白银现货怎么开户,需要投入多少钱?

在白银投资市场中,有一种交易产品种类,它能够提供给人们稳定的理财环境,还具有辨别的交易环境。这种白银理财产品就是现货白银,也有一部分投资者将其称为白银现货。为了人们对这一产品具有更加清晰的认识,今天万洲金业…

行情分析 - - 加密货币市场大盘走势(11.23)

大饼昨日又开始了回调,因为FTF消息,而实际还是要下跌的,耐心等待即可。 空单策略:入场37300 止盈34000-33000 止损39000 以太昨日上涨也很激励,目前上涨打了止损,现在入场是好的机会,等待即可。…