python yield关键字(生成器Generators)(延迟计算、惰性求值、缓式求值)(生成器表达式generator expressions)(生成器表达式、链接生成器)

本文介绍了Python中的yield关键字,作为生成器的核心,它提供了内存高效、代码简洁以及处理大型数据和复杂迭代的解决方案。文章详细讲解了基本用法、内存效率提升、生成器表达式、链接生成器和在递归中的应用。
摘要由CSDN通过智能技术生成

理解Python的yield关键字 (Understanding Python’s yield Keyword)

生成器简介 (Introduction to Generators)

In the Python programming language, the concept of generators provides a powerful tool for creating iterators(迭代器) in a more concise and memory-efficient way.
在Python编程语言中,生成器的概念提供了一种用更简洁、更节省内存的方式创建迭代器的强大工具。

A generator is a special type of iterator, which allows you to pause the execution of a function and return an intermediate(中间的) result, resuming(继续、恢复) from where it left off(离开) on subsequent(后续的) calls.
生成器是一种特殊类型的迭代器,它允许你暂停函数的执行并返回一个中间结果,然后在后续调用时从中断的地方继续执行。

This is achieved using the yield keyword.
这是通过使用yield关键字实现的。

yield关键字 (The yield Keyword)

The yield keyword transforms(转换) a function into a generator.
yield关键字将函数转换成生成器。

When a function contains at least one yield statement, it becomes a generator function.
当一个函数包含至少一个yield语句时,它就变成了一个生成器函数。

This means that when you call the function, instead of executing its body(主体) immediately, it returns a generator object.
这意味着当你调用这个函数时,它不会立即执行其主体,而是返回一个生成器对象。

This object can then be iterated over(逐个;遍历), one value at a time.
然后可以一次迭代一个值地遍历这个对象。

yield的基本用法 (Basic Usage of yield)

To understand how yield works, let’s start with a simple example:
要理解yield是如何工作的,让我们从一个简单的例子开始:

def count_up_to(max):
    count = 1
    while count <= max:
        yield count
        count += 1


counter = count_up_to(5)

print(counter)

for num in counter:
    print(num)

This code will output:
这段代码将输出:

<generator object count_up_to at 0x7f9e5a298660>
1
2
3
4
5

In this example, the count_up_to function yields numbers from 1 to a maximum provided by the user.
在这个例子中,count_up_to函数生成了从1到用户提供的最大值的数字。

Each time the generator’s __next__() method is called (implicitly(暗中地) by the for-loop(for循环)), the function resumes(恢复) execution right after the yield statement, continues to the next iteration of the while-loop, and pauses at the yield statement again.
每次调用生成器的__next__()方法(由for循环隐式调用)时,函数会在yield语句之后立即恢复执行,继续执行while循环的下一次迭代,然后再次在yield语句处暂停。

(从调试上来看,count_up_to函数是for num in counter:访问迭代器时才执行的,执行yield每获得一个元素后,函数暂停,然后下一次for循环访问时,再从yield的下一句恢复)

使用yield的优势 (Advantages of Using yield)

内存效率 (Memory Efficiency)

One of the primary advantages of using yield is memory efficiency.
使用yield的一个主要优势是内存效率。

Generators do not compute all the items they yield at once(一次性); they generate each item one at a time(每次一个) and only when requested.
生成器不会一次性计算它们生成的所有项;它们一次生成一个项,且只在被请求时生成。

This lazy evaluation(缓式求值) makes generators ideal for working with large datasets or streams of data where you don’t want to load everything into memory.
这种懒惰计算使得生成器非常适合处理大型数据集或数据流,在这些情况下你不想将所有数据一次性加载到内存中。

简化代码 (Simplifying Code)

Generators can help simplify code that would otherwise(在其他情况下) require managing the iteration state manually.
生成器可以帮助简化那些需要手动管理迭代状态的代码。

在这个句子中,“otherwise”意味着“如果不是这样的话”或“在其他情况下”。它用来指出如果没有使用生成器的情况,代码将需要手动管理迭代状态,这可能会使代码更复杂。因此,使用生成器可以简化这一过程,避免了在没有生成器的情况下可能遇到的复杂性。简而言之,“otherwise”在这里强调了使用生成器相对于不使用它们时代码简化的对比效果。

在这个句子中的“that”是一个引导词,用来引导一个定语从句。定语从句是用来修饰或者限定名词或代名词的从句,在这个例子中,它修饰前面的名词“code”。这个定语从句(that would otherwise require managing the iteration state manually)详细描述了“code”,指出这是一种如果没有使用生成器,则需要手动管理迭代状态的代码。因此,“that”在这里的作用是连接主句和定语从句,帮助提供关于“code”更详细的信息。

By handling iteration complexity internally(内部地), yield allows for cleaner, more readable code.
通过内部处理迭代复杂性,yield使代码更清晰、更易读。

高级生成器模式 (Advanced Generator Patterns)

Generators can be used in more advanced scenarios beyond(除…之外) simple iteration. Here are a few patterns:
简单迭代之外的更高级场景。以下是一些模式:

生成器表达式 (Generator Expressions)

Similar to list comprehensions(列表推导式), generator expressions allow for creating generators in a concise(简洁的) syntax(语法). They are surrounded by parentheses(圆括号) () instead of square brackets []:
类似于列表推导式,生成器表达式允许以简洁的语法创建生成器。它们用圆括号()而不是方括号[]包围:

“List comprehensions” 被翻译成“列表推导式”是因为这个功能允许通过一个已有的列表(或任何可迭代对象)来创建一个新列表。这个过程涉及到“推导”(即根据一定的逻辑推理或计算出结果)新列表的元素。在这个上下文中,“推导式”指的是通过一个表达式来推导出一系列值。

  • List(列表):这一部分很直接,指的是Python中的列表数据结构。
  • Comprehensions(推导式):这一部分描述了如何从一个已有的序列(列表、集合、字典等)中,通过一定的表达式推导出一个新的序列。"Comprehension"在这里被理解为对数据的一种“理解”或“推导”,通过对原数据的处理和转换来创建新的数据结构。

因此,“列表推导式”准确地捕捉了这个特性的本质:通过对一个列表的元素进行推导和转换,根据一定的规则和条件,来快速创建出一个新的列表。这个过程既简洁又高效,能够在一行代码内完成原本可能需要多行循环语句来实现的任务。

squares = (x**2 for x in range(10))
for square in squares:
    print(square)

在这里插入图片描述

链接生成器 (Chaining Generators)

Generators can be chained together, allowing for the composition(组合方式) of complex data processing pipelines. Here’s how you can chain two generators:
生成器可以被链接在一起,允许组成复杂的数据处理管道。以下是如何链接两个生成器的方法:

def even_numbers(numbers):
    for number in numbers:
        if number % 2 == 0:
            yield number


def multiply_by_three(numbers):
    for number in numbers:
        yield number * 3


# Chain generators
numbers = range(10)
even_nums = even_numbers(numbers)
result = multiply_by_three(even_nums)

for item in result:
    print(item)

在这里插入图片描述

注:even numbers是偶数

This example filters even numbers from a range and then multiplies them by three, demonstrating a simple data processing pipeline.
这个例子从一个范围中过滤出偶数,然后将它们乘以三,展示了一个简单的数据处理管道。

在递归中使用yield (Using yield with Recursion)

yield can also be used in recursive functions to traverse(遍历) data structures. Here’s an example of traversing a simple binary tree:
yield也可以用在递归函数中遍历数据结构。这里有一个遍历简单二叉树的例子:

class TreeNode:
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right


def traverse_in_order(node):
    if node is not None:
        yield from traverse_in_order(node.left)
        yield node.value
        yield from traverse_in_order(node.right)


# Example tree
root = TreeNode(1, TreeNode(2), TreeNode(3))

for value in traverse_in_order(root):
    print(value)

在这里插入图片描述

This uses yield from to yield all values from a generator function recursively, effectively flattening(变平) the results from a tree traversal(遍历) into a single iterable sequence.
这使用了yield from从递归的生成器函数中产生所有值,有效地将树遍历的结果扁平化为一个可迭代序列。

结论 (Conclusion)

The yield keyword in Python is a cornerstone of creating generators, enabling efficient data processing and simplifying the management of iterators. Its ability to pause and resume functions makes it invaluable for working with large datasets, streaming data, and implementing complex iteration patterns. Through examples, we’ve explored its basic usage, advantages, and advanced patterns, demonstrating its versatility and power in various programming scenarios.
Python中的yield关键字是创建生成器的基石,它使数据处理更高效并简化了迭代器的管理。它暂停和恢复函数的能力在处理大型数据集、数据流和实现复杂迭代模式时非常宝贵。通过示例,我们探讨了它的基本用法、优势和高级模式,展示了它在各种编程场景中的多功能性和强大性。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dontla

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值