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

在这里插入图片描述

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

1. 生成器Generators

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

1.1 语法

python">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 简单示例

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

python">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 处理大数据集

python">"""
    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 无限序列

python">"""
    无限序列
    实现斐波那契数列
"""
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 懒加载

python">"""
    懒加载-读取数据库记录
"""
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 状态机

python">"""
    状态机
"""
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 异步编程

python">"""
    异步编程-协程
"""
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 语法

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

python">gen_expr = (x for x in range(5))

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

2.2 应用场景

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

2.3 简单示例

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

python">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))
python"># 生成器表达式示例:生成包含偶数的生成器
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 列表筛选

python">"""
    列表筛选
"""
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 简单转换

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

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

在这里插入图片描述

2.4.3 迭代

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

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

在这里插入图片描述

2.4.4 过滤

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

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

在这里插入图片描述

2.4.5 字典生成

python">"""
    字典生成
"""
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.niftyadmin.cn/n/5219074.html

相关文章

C++(20):通过starts_with/ends_with检查字符串

C20提供了starts_with用于检查字符串是否以某个字符串开始&#xff0c;ends_with用于检查是否以某个字符串结束&#xff1a; #include <iostream> #include <string> using namespace std;int main() {string str "hello and 88";cout<<str.star…

护眼灯有效果吗?对孩子眼睛好的护眼台灯推荐

2022年12月29日&#xff0c;内蒙古消费者协会发布的比较试验结果显示&#xff0c;被检测的35款读写作业台灯样品中有12款标记项目不符合国家强制性标准要求&#xff0c;占被检测样品的34%&#xff0c;其中博士有成、大力智能、霍尼韦尔位列质量黑榜。该从哪些方面注意权衡做好选…

python:特殊参数 *args 、**kwargs、/、 *的解释以及定义实例

python&#xff1a;特殊参数 *args 、**kwargs、/、 *的解释以及定义实例 文章目录 python&#xff1a;特殊参数 *args 、**kwargs、/、 *的解释以及定义实例*args 参数**kwargs 参数/ 和 * 为限制参数定义实例总结 在 Python 中&#xff0c;函数可以定义任意数量的参数&#x…

Jenkins Pipeline应用实践

Jenkins Pipeline是一种可编程的、可扩展的持续交付管道&#xff0c;允许您使用脚本来定义整个软件交付过程。 以下是使用Jenkins Pipeline创建和配置流水线的基本步骤。 Part 01. 创建一个Pipeline Job 在Jenkins中创建一个新的"Pipeline"类型的Job。 以下是在Je…

Bitcoin SV 和 Bitcoin Core 之间首次跨链原子交换

我们已经执行了 Bitcoin SV 和 Bitcoin Core 之间的首次原子交换。 这一成就代表了比特币 SV 的重大进步&#xff0c;以去信任的方式促进了与其他区块链的无缝互操作性。 图片源自Gemini 在上一篇文章中&#xff0c;我们解释了原子交换的高级理论。 我们深入研究了使用哈希时间…

折线图-line

业务组件调用代码 <lineCom :title"lineComProps.title" :legendDataList"lineComProps.legendDataList":FeatureList"lineComProps.FeatureList" :xAxisData"lineComProps.xAxisData":seriesMultipleFlag"lineComProps.serie…

lipid signaling

--Introduction to Lipid Signaling (csbsju.edu)

时间序列预测 — LSTM实现单变量滚动风电预测(Keras)

目录 1 数据处理 1.1 数据集简介 1.2 数据集处理 2 模型训练与预测 2.1 模型训练 2.2 模型滚动预测 2.3 结果可视化 1 数据处理 1.1 数据集简介 实验数据集采用数据集5&#xff1a;风电机组运行数据集&#xff08;下载链接&#xff09;&#xff0c;包括风速、风向、温…