生成器惰性机制一窥(2)

def add(a,b):
    return a+b

def test():
    for r_i in range(4):
    yield r_i

g = test()

for n in [2,10,5]:
    g = (add(n,i) for i in g)

log(list(g))
观察上面一串代码,分解:
首先可以确定g的初始值为test(),即(0,1,2,3)
然后分解for循环,如下:
n = 2:

g = (add(n,i) for i in g)

n = 10:

g = (add(n,i) for i in g)

n = 5:
g = (add(n,i) for i in g)
当n = 2和n = 10的时候,因为没有取值,所以g没有变化。最后循环在n=5结束,此时取值:
g = (add(n,i) for i in (add(n,i) for i in (add(n,i) for i in g)))
将上面公式中所有n变为5,g此时为(0,1,2,3),导出结果:
[15, 16, 17, 18]
难点1:为什么后面for循环中的g是前面g的值?
example:
n = 2时,g = 20;
n = 10时,g = 20*g
那么,最后的g是不是20乘以前面的值呢?
注意:每一次g都是一个生成式,而不是单纯的数值列表。n = 2时,生成式g需要传入一个g = test()的值,依次类推。
难点2:为什么n=2和n=10时,g的数值没有变化?
生成器值的变化只有导出(__next__),传递参数并改变前一个yield的值(send),和for中默认的next循环导出。
而在n=2和n=10的时候,并没有导出值,导致g一直存在,并进入【难点1】的公式。
生成器的惰性机制,导致只有在取值的时候,值才会代入,否则,只是一串代码。具体,可参考上一篇。
if:
最后的log在for循环内会得到什么结果呢?

for n in [2,10,5]:
    g = (add(n,i) for i in g)
    log(list(g))
那么又回到上一篇的结论了。当g第一次循环的时候,其数值已经被取走,后面的两次循环g为空值,所以导出结果为:

[2, 3, 4, 5]
[]
[]
posted @ 2019-07-02 10:54  Mana66ccff  阅读(148)  评论(0)    收藏  举报