首先感谢:http://www.cnblogs.com/zhuhaofeng/articles/9469897.html,这篇博客的作者,把这段代码的过程一步步进行的分解,希望可以帮助大家更好的理解这段代码。
从而,更好的理解生成器。要理解这段代码,需要先了解生成器的两个特点:
1.惰性机制
2.生成器,在被调用之前,只是代表着一段没有被执行过的代码
---------------------------------------下面是最开始的代码--------------------------------------------------------
1.0
有一个有意思的python面试题,是下面的这个样子
def add(a,b): #普通求和函数
return a + b
def test(): #生成器函数
for r in range(4):
yield r
g=test()
for n in [2,10]:
g=(add(n,i) for i in g)
print(list(g))
---------------------------------------下面是第一步分解-------------------------------------------------------
1.1:代码块注释如下(还是上面的内容,只是注释加多了)
def add(a,b): #普通求和函数
return a + b
def test(): #生成器函数
for r in range(4):
yield r
g=test() #获取生成器对象,后面的操作都指向这个对象,这和直接执行fun()函数销效果是不一样的
for n in [2,10]: #因为前面已经定义了生成器g,这个for循环的代码块等于是重新定义了变量g,
g=(add(n,i) for i in g) #重新定义的这个变量g也是一个生成器,使用推导式定义的生成器
print(list(g)) #list自带for方法,所以list(g)会一次性把上面列表生成器的值拿完
---------------------------------------下面是第二步分解---------------------------------------------------------
1.2:代码简化(对上面的代码做了简化,但是都是等效的,主要是对for循环做了简化)
def add(a,b): #普通求和函数
return a + b
def test(): #生成器函数
for r in range(4):
yield r
g=test()
n=2 #这一行到下一步后,就没有了,我开始没理解。为什么就可以省略了?答案是当n=2时,只是生成了一个生成器,而并没有执行括号里面的代码,因为这时,没有人去调用
#这个生成器,所以这时的g只是代表着一段代码:(add(n,i) for i in g)。
g=(add(n,i) for i in g)
n=10
g=(add(n,i) for i in g)
print(list(g))
---------------------------------------下面是第三步分解-----------------------------------------------------------
1.3:代码简化(对上面的代码做了简化,但是都是等效的,主要是对n重新赋值的过程做了简化)
def add(a,b):
return a + b
def test():
for r in range(4):
yield r
g=test()
n=10 #和上面的代码做比较,n重新赋值了两次,第二次已经把一次的赋值覆盖掉了,但是g因为前面做过定义,需要带入。
#因为n=2时,没有执行括号里面的代码,所以,走到了n=10。但是,这时括号里面的代码还是没有执行,这个时候的g也不过是
#一段代码:(add(n,i) for i in g)。而且,这时的n已经被重新赋值了,n=10.已经在内存中存在了。
g=(add(n,i) for i in (add(n,i) for i in g))#这里最外层括号里的g,是n=2时的生成器,第二步已经说过,那时的g只不过是一段代码,所以直接带过来就好了。
print(list(g))
---------------------------------------下面是第四步分解-----------------------------------------------------------
1.4:代码简化(对上面的代码做了简化,但是都是等效的,带入数字10)
def add(a,b):
return a + b
def test():
for r in range(4):
yield r
g=test()
g=(add(10,i) for i in (add(10,i) for i in g))
print(list(g))#走到这里时,因为list中有__next__(),所以开始跟生成器要值了,生成器开始循环起来。
#因为for循环自带__next__方法,所以for循环作用于生成器的时候也是一次性遍历完的,并不需要单独的在一个一个执行next
#分别带入i值0,1,2,3,可以生成g的一个生成器结果,再通过list(g)一次性拿完
-----------------------------------------------------------------------------------------------