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

在这里插入图片描述

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

1. 生成器(Generators

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

1.1 语法

def my_generator():yield 1yield 2yield 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, 1while True:yield aa, 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 queryrecords = 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 squaresxvec = [10, 20, 30]
yvec = [7, 5, 3]
sum(x*y for x,y in zip(xvec, yvec))     # dot productunique_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.hqwc.cn/news/211260.html

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

相关文章

实现自动化构建与集成:Jenkins与SVN整合的指南

Jenkins整合SVN 前言(非必须):配置Jenkins的CSRF1、新建任务2、 配置SVN3、配置Maven:进行编译打包4.1、发布到WEB容器(第一种:将项目放在webapps下)4.2、发布到WEB容器(第二种:将项目名称修改为…

文心一言 VS 讯飞星火 VS chatgpt (141)-- 算法导论12.1 1题

一、用go语言,对于关键字集合(1,4,5,10,16,17,21),分别画出高度为 2、3、4、5和6的二又搜索树。 文心一言: 以下是用Go语言为给定的关键字集合(1, 4, 5, 10, 16, 17, 2…

VR云游:让旅游产业插上数字化翅膀,打造地方名片

自多地入冬降温以来,泡温泉成了许多人周末度假的选择,在气温持续走低的趋势下,温泉游也迎来了旺季;但是依旧有些地区温度依旧温暖,例如南京的梧桐美景也吸引了不少游客前去打卡,大家穿着汉服与金黄的树叶合…

openGL之纹理 :第二课

#include "glew.h" #include "glfw3.h" #include "SOIL2.h"//如何解析输入的数据流 0,1,2 分三部分 GLchar * vertextSrc " #version 330 core \n \layout (location 0) in vec3 position; \layout (location 1) in vec3 col…

I Doc View在线文档预览系统RCE漏洞(QVD-2023-45061)

0x01 产品简介 iDocView是一个在线文档解析应用,旨在提供便捷的文件查看和编辑服务。 0x02 漏洞概述 漏洞成因 本次漏洞出现在在线文档解析应用中的远程页面缓存功能。具体问题在于该应用未能对用户输入的URL进行充分的安全验证,从而导致存在安全隐患…

生命周期评估(LCA)与SimaPro碳足迹分析

SimaPro提供最新的科学方法和数据库以及丰富的数据,使您可以收集和评估产品和流程的环境绩效。通过这种方式,您可以将改变公司产品生命周期的想法提交给您的同事,以便阐明您的业务未来。 SimaPro软件的特点和功能: 完全控制产品生…

品牌如何利用情绪营销打出知名度

“悦己文化”和“她经济”的兴起让人们更加关注自己的内心感受,同时“发疯文学”、“精神内耗”等热词都体现了当代人为了缓解压力而为情绪消费的趋势,品牌想要留住消费者,就必须不断迭代,直面消费者需求,今天媒介盒子就来和大家聊…

git本地账户如何从一台电脑迁移到另外一台

为了表述方便,我们此处用旧电脑、新电脑指代。 在新电脑上安装git 例如,我旧电脑上安装的git版本是2.33.1版本,新电脑安装git的版本是2.43.0,这不妨碍迁移。 将git的全局配置文件从旧电脑拷贝到新电脑 Git的全局配置文件&…

边海防可视化智能视频监控与AI监管方案,助力边海防线建设

一、背景与需求 我国有3万多公里的边境线和海岸线,随着我国边海防基础设施建设的快速发展,边海安防也逐渐走向智能化。传统人工巡防的方式已经无法满足边海智能化监管的需求,在沿海、沿边地区进行边海智慧安防视频监控系统等边海防基础设施建…

解决 Windows11 记事本默认加载之前文本内容的问题

解决 Windows11 记事本默认加载之前文本内容的问题 点击窗口右上角的齿轮 在菜单中展开 记事本启动时 的选项,将 从上一个会话打开内容 改为 开启新窗口,如下图所示: 这样即可实现。

迁新址 启新程|美创科技杭州总部乔迁仪式圆满举行

“迁新址 启新程” 2023年11月21日 美创科技杭州总部乔迁仪式隆重举行 杭州未来科技城管委会、余杭国投集团、浙江省网络空间安全协会、浙江鸿程、华睿投资、金艮投资、如山资本、赛伯乐投资、宽带资本、普华投资、国中创投、密码资本、东方富海、之江商学、阿里云、联通&…

leetCode 2925. 在树上执行操作以后得到的最大分数 + 正则难反 + 树形 DP

2925. 在树上执行操作以后得到的最大分数 - 力扣(LeetCode) 有一棵 n 个节点的无向树,节点编号为 0 到 n - 1 ,根节点编号为 0 。给你一个长度为 n - 1 的二维整数数组 edges 表示这棵树,其中 edges[i] [ai, bi] 表示…