代码之家  ›  专栏  ›  技术社区  ›  Peter Barrett Bryan

生成器的惰性Python行为

  •  0
  • Peter Barrett Bryan  · 技术社区  · 8 年前

    好的,马上:我知道Python生成器很懒惰。也就是说,这让我大吃一惊;我不明白。蟒蛇的朋友们,请不要因为我对这个问题的无知而把我钉在十字架上。这并不是在现实世界的发展情况中遇到的,只是一直困扰着我的好奇心。

    def gen1(n):
        print('gen1')
        return 1
    
    def gen2(n):
        print('gen2')
        return 2
    
    print(gen2(gen1(0)))
    

    这个示例完全符合我的预期,它先打印gen1,然后打印gen2,然后打印gen2。

    以下代码示例没有:

    def gen1(n):
        print('gen1')
        yield 1
    
    def gen2(n):
        print('gen2')
        yield 2
    
    print(list(gen2(gen1(0))))
    

    相反,它只打印“gen2”和[2]。等一下,它先调用gen2?它从不评估gen1?什么?!在引擎盖下,它是如何实现魔鬼魔法的?这里到底发生了什么?所以最外层的东西被确定为生成器,它会引发一些内省,从而确定对内部生成器的评估是不必要的?追踪这种行为的信息量更大的方法是什么?

    1 回复  |  直到 8 年前
        1
  •  1
  •   user2390182    8 年前

    生成器中的代码不会在创建生成器时执行,而是在被驱动构造(如循环、理解或其他生成器)使用时执行。以下内容可能会澄清这一问题:

    >>> def gen1(n):
    ...     print('gen1')
    ...     yield 1
    ...     print('gen1')
    ...     yield 2
    ... 
    >>> g = gen1(5)  
    # this returns the generator object, 
    # but does not execute any code in it, hence 'lazy'
    >>> for x in g:  
            # each 'x' assignment executes code til the next 'yield'
    ...     print x
    ... 
    gen1
    1
    gen1
    2
    

    您可能想知道程序如何在第一个 yield 语句,但解释器首先检查整个函数体,如果有 产量 该函数是一个生成器函数,其主体在调用时不执行。