python 生成器笔记

在做牛客网上的python第一道题的时候就蒙了,看来还是生成器没学好。
题目如下:

def bar(n):
   m=n
   while True:
      m+=1
      yield m     
      b = bar(3)
      print b.next()

这里回顾下生成器的知识,基础的就不说了,就一点:就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

下面举几个例子:

def bar_1(n):
   m=n
   for i in range(3):
      m+=1
      yield m     
      print 'i am here'

a=bar_1(3)
# 在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行
print 'a:',a.next() 

输出结果:

a: 4

因为生成器只有在调用next()的时候执行,这里调用后遇到yield就返回了结果4,而下面没有继续调用next(),所以执行就此结束。

def bar_2(n):
   m=n
   for i in range(5):
      m+=1
      yield m     
      print 'i am here'

a=bar_2(3)
for i in range(3):
    print i,'->',a.next()

运行结果:

0 -> 4
1 -> i am here
5
2 -> i am here
6

这里在for中循环调用3次next(),也就是在遇到yield返回后,因为再次调用next()而继续执行下面的语句。这里要注意的是1 -> i am here5是在for i in range(3)`中一次循环中执行的。

def bar_4(n):
   m=n
   for i in range(5):
      m+=1
      yield m     
      print 'i am here'

a=bar_4(3)
for i in a:
    print 'i->',i

运行结果:

i-> 4
i am here
i-> 5
i am here
i-> 6
i am here
i-> 7
i am here
i-> 8
i am here

从结果可以看出,直接用for循环来遍历生成器对象更方便,打印出的结果也很清晰,也即是for i in range(5)执行完所有的循环,不再受到外部循环的边界限制。

def bar_5(n):
   m=n
   for i in range(6):
      m+=1
      yield m     
      print 'i->',i   
      b = bar_5(5)
      print 'b=',b.next()

a=bar_5(3)
for i in a:
    pass

运行结果:

i-> 0
b= 6
i-> 1
b= 6
i-> 2
b= 6
i-> 3
b= 6
i-> 4
b= 6
i-> 5
b= 6

我的理解是,这里每次执行b = bar_5(5)后遇到yield就中断,遇到b.next()后就打印首元素后而结束。这里的总体循环次数是根据for i in range(6)而定。

下面就是运行题目的程序了:

def bar_5(n):
   m=n
   while True:
      m+=1
      yield m     
      b = bar_5(3)
      print b.next()

a=bar_5(1)
for i in a:
    pass

运行结果:

4
4
4
4
4
4
4
4
4
4
4
4
4
...

这里由于控制循环次数的是while True,所以是死循环,而每次打印的是生成器b的首元素,也既是4。

以上是查资料加自己的理解,如有错误,还望指正。

猜你喜欢

转载自blog.csdn.net/lilong117194/article/details/79981122