• Python中的yield关键字


    基本概念

    yield 是 Python 中的一个关键字,主要在定义生成器函数时使用。使用 yield 的函数在调用时返回一个特殊的迭代器,称为生成器。不同于常规的函数返回一个单一的值(如数字、字符串或其他对象),带有 yield 的函数允许返回一个序列的值,并且在每次产生一个值后“暂停”函数的执行。

    基本用法

    考虑以下简单的生成器函数,它使用 yield 来生成三个整数:

    def simple_generator():
        yield 1
        yield 2
        yield 3
    
    • 1
    • 2
    • 3
    • 4

    当调用这个函数时,它不会像常规函数那样立即执行,而是返回一个生成器对象:

    gen = simple_generator()
    
    • 1

    要从生成器中获取值,可以使用 next() 函数:

    print(next(gen))  # 输出: 1
    print(next(gen))  # 输出: 2
    print(next(gen))  # 输出: 3
    
    • 1
    • 2
    • 3

    函数的“暂停与继续”

    当生成器函数执行到 yield 语句时,它会产生一个值,然后暂停函数的执行。函数的状态(包括局部变量、指令指针、内部堆栈等)都被保存下来,以便后续的恢复。当再次调用 next() 时,函数从上次 yield 语句的下一行开始执行,直到再次遇到 yield

    这种“暂停与继续”功能使得生成器在处理流式数据或表示无限序列时非常有用。

    与 return 的区别

    在生成器函数中,return 有一个特殊的意义。当在生成器函数中使用 return(没有或有值),它都表示生成器的终结,并且如果有值,该值会作为 StopIteration 异常的参数返回。

    例如:

    def generator_with_return():
        yield 1
        yield 2
        return "end of generator"
        yield 3  # 这一行永远不会被执行
    
    • 1
    • 2
    • 3
    • 4
    • 5

    当迭代到 yield 2 之后,下一次迭代会触发一个 StopIteration 异常,并携带消息 “end of generator”。

    在循环中使用 yield

    yield 常常与循环结构结合使用,以生成一个序列的值【1】。例如:

    def count_up_to(n):
        count = 1
        while count <= n:
            yield count
            count += 1
    
    • 1
    • 2
    • 3
    • 4
    • 5

    使用 yield from

    Python 3.3 引入了 yield from 语法,它允许在一个生成器中委托部分操作到另一个生成器。这使得生成器的组合和重用变得更加简单。

    def generator_one():
        yield 1
        yield 2
    
    def generator_two():
        yield 3
        yield 4
    
    def combined_generator():
        yield from generator_one()
        yield from generator_two()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    调用 combined_generator() 将按顺序产生 1, 2, 3 和 4。

    总之,yield 是 Python 中创建生成器的关键工具,它为流式数据处理、协程以及其他高级用法提供了基础。

    示例:斐波那契数列生成器

    斐波那契数列是一个无限序列,在这个序列中,前两个数字是 1 和 1,随后的每个数字都是前两个数字之和。数列的前几个数字是:1, 1, 2, 3, 5, 8, 13, …。

    以下是一个使用 yield 生成斐波那契数列的生成器:

    def fibonacci_generator(n):
        """
        生成前n个斐波那契数。
        """
        a, b = 0, 1
        count = 0
        while count < n:
            a, b = b, a + b
            yield a
            count += 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    使用这个生成器,可以生成任何长度的斐波那契数列。例如,生成前10个斐波那契数:

    for num in fibonacci_generator(10):
        print(num)
    
    • 1
    • 2

    输出:

    1
    1
    2
    3
    5
    8
    13
    21
    34
    55
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这个生成器的好处是可以按需生成斐波那契数,而不必预先计算整个序列。这种按需生成的特性使得处理大数据或无限序列变得可能,因为在任何时候都不需要在内存中存储整个序列。


    注【1】:count_up_to 函数是一个生成器函数,当调用它时,它会返回一个生成器对象。要从这个生成器中获取值,可以使用 next() 函数进行迭代,或者将生成器放入循环中以便连续地获取所有值。

    以下是如何使用 count_up_to 函数的一些示例:

    使用 next()

    gen = count_up_to(3)
    
    print(next(gen))  # 输出: 1
    print(next(gen))  # 输出: 2
    print(next(gen))  # 输出: 3
    
    • 1
    • 2
    • 3
    • 4
    • 5

    当再次调用 next(gen) 时,因为已经迭代完所有的值,所以会触发一个 StopIteration 异常。

    使用 for 循环

    for number in count_up_to(5):
        print(number)
    
    • 1
    • 2

    输出:

    1
    2
    3
    4
    5
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这是最常见的使用生成器的方式,因为 for 循环会自动处理 StopIteration 异常并终止循环。

    使用 list()

    如果想直接获取生成器的所有值并将它们放入一个列表中,可以使用 list()

    numbers = list(count_up_to(4))
    print(numbers)  # 输出: [1, 2, 3, 4]
    
    • 1
    • 2

    这种方法可以方便地将生成器的输出转换为一个列表,但请注意,对于产生大量数据的生成器,这种方法可能会消耗大量的内存。

  • 相关阅读:
    ELK日志收集系统
    【11】二进制编码:“手持两把锟斤拷,口中疾呼烫烫烫”?
    作为新人,如何快速融入新团队?用好这8个点
    【建议背诵】软考高项考试案例简答题汇总~(3)
    火山引擎 DataLeap 的 Data Catalog 系统公有云实践
    Http状态401,弹出原生登录弹窗问题
    免杀技术实际演示
    ansible DBA常用场景命令小集
    JAVA学习-----TreeMap
    5359: 【图论】有向图连接边数(图的遍历前置)
  • 原文地址:https://blog.csdn.net/weixin_43844521/article/details/133692132