简体   繁体   English

生成器的惰性Python行为

[英]Lazy Python behavior with generators

OK, right off the bat: I know Python generators are lazy. 好的,马上开始:我知道Python生成器是惰性的。 That said, this is blowing my mind; 话虽如此,这真让我震惊。 I don't get it. 我不明白 Pythonic friends, please don't crucify me for the ignorance of this question. Python朋友,请不要因为这个问题的无知而将我钉在十字架上。 This was not encountered in a real-world development situation, just a curiosity that has been bothering me. 在现实世界的开发情况中并没有遇到这种情况,只是好奇心一直困扰着我。

def gen1(n):
    print('gen1')
    return 1

def gen2(n):
    print('gen2')
    return 2

print(gen2(gen1(0)))

This sample does exactly what I expect it to do, it prints gen1 then gen2 then 2. 该示例完全按照我的期望进行操作,先输出gen1然后gen2然后2。

The following code sample does not: 以下代码示例不包含:

def gen1(n):
    print('gen1')
    yield 1

def gen2(n):
    print('gen2')
    yield 2

print(list(gen2(gen1(0))))

Instead, it just prints 'gen2' and [2]. 相反,它仅打印“ gen2”和[2]。 So wait a hot sec, it calls gen2 first? 因此,等待一秒钟,它首先调用gen2吗? It never evaluates gen1? 它从不评估gen1吗? WHAT?! 什么?! Under the hood, how does it pull that devil magic off? 在引擎盖下,它如何将魔鬼拉下来? What is actually taking place here? 这里实际上发生了什么? So the outermost thing is identified as a generator and it triggers some introspections that identifies that evaluation of the inner generator is unnecessary? 因此,最外层的事物被识别为生成器,并且触发了一些内省,这些内省表明不需要对内部生成器进行评估? What is a more informative way of tracing this behavior? 跟踪此行为的更有用的方法是什么?

The code in the generator is not executed when the generator is created, but when it is consumed by a driving construct like a loop, a comprehension or another generator. 生成器中的代码不是在创建生成器时执行的,而是在被诸如循环,理解或其他生成器之类的驱动结构所使用时执行的。 The following might clear this up: 以下内容可能会清除此问题:

>>> 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

You might wonder how the program knows it is a genrator before the first yield statement, but the interpreter checks the entire function body first, and if there is any yield the function is a generator function whose body is not executed when called. 您可能想知道程序如何在第一个yield语句之前知道它是一个生成器,但是解释器会首先检查整个函数体,并且如果有任何yield该函数是一个生成器函数,其主体在调用时不会执行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM