生成器使用总结: 
1.生成器的好处是可以一边循环一边进行计算,不用一下子就生成一个很大的集合,占用内存空间。生成器的使用节省内存空间。 
2.生成器保存的是算法,而列表保存的计算后的内容,所以同样内容的话生成器占用内存小,而列表占用内存大。每次调用 next(G) ,就计算出 G 的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出 StopIteration 的异常。 
3.使用for 循环来遍历生成器内容,因为生成器也是可迭代对象。通过 for 循环来迭代它,不需要关心 StopIteration 异常。但是用for循环调用generator时,得不到generator的return语句的返回值。如果想要拿到返回值,必须用next()方法,且捕获StopIteration错误,返回值包含在StopIteration的value中。 
4.在 Python 中,使用了 yield 的函数都可被称为生成器(generator)。生成器是一个返回迭代器的函数,只能用于迭代操作。更简单点理解生成器就是一个迭代器。 
5.一个带有 yield 的函数就是一个 generator,它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用 next())才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yield 语句就会中断,保存当前所有的运行信息,并返回一个迭代值,下次执行next() 方法时从 yield 的下一个语句继续执行。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。生成器不仅“记住”了它数据状态;生成器还“记住”了它在流控制构造中的位置。

当然其实平常很少用到next(),我们直接用for循环就可以遍历一个generator,其实for循环的内部实现就是不停调用next()。

可迭代对象(Iterable)和迭代器(Iterator)的概念:

可迭代对象(Iterable)

可以直接作用于for循环的对象统称为可迭代对象:Iterable。包括集合数据类型(list、tuple、dict、set、str等)和生成器(generator)。

迭代器:Iterator

它表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。 
把list、dict、str等Iterable变成Iterator可以使用iter()函数:

生成器(generator)本身就是一个迭代器;

list、dict、str等可迭代对象(Iterable) 要使用iter()函数才能变成迭代器(Iterator)

生成器有两种:       

生成器函数        

生成器表达式 

生成器函数的定义:  
      含有yield语句的函数是生成器函数,此函数被调用将会返回一个生成器对象

简单来说:只要在def中有yield关键字的 就称为 生成器

      yield翻译为产生(或生成)

说明:
            yield 用于def函数中,目的是将此函数用生成器函数使用
            yield 用来生成数据,供迭代器和next(it)函数使用

def myyield():
    print("即将生成2")
    yield 2
    print("即将生成3")
    # return '在生成3之前用return返回'  将会发生异常
    yield 3
    print("即将生成4")
    yield 4
    print("即将生成5")
    yield 5
    print("生成器生成结束")
    yield 
#for x in  myyield():
#    print(x) 
# 调用生成器函数来创建一个生成器,此生成器能生成 2,3,4,5
gen = myyield()
it = iter(gen)  #用生成器拿到对应的迭代器
print(next(it)) #此时生成器函数才开始执行,并遇到yield停止 2
print(next(it)) #访问迭代器 3
print(next(it)) #4   
print(next(it)) #5
print(next(it)) #生成器生成结束

生成器表达式:

语法:

把一个列表生成式的[ ]改成 (),就创建了一个generator:

(表达式 for 变量 in 可迭代对下哪个 [if 真值表达式])
        作用:
            用推导式形式创建一个新的生成器
        说明:
            if子句可以省略

gen = (x**2 for x in range(1,5))
it = iter(gen)
print(next(it))   #1
print(next(it))   
print(next(it))   #9
print(next(it))   #16
print(next(it))   #StopInteration

生成器表达式和列表推导式的区别: 生成器表达式是现用现生成,列表推导式是一次生成静态数据

#列表推导式

l = [2,3,5,7]
l2 = [x ** 2 + 1 for x in l]
it = iter(l2)
print(next(it))   # 5
l[1] = 30
print(next(it))   # 10
 
#生成器表达式

l = [2,3,5,7]
gen = (x ** 2 + 1 for x in l)
it = iter(gen)
print(next(it))   #5
l[1] = 30
print(next(it))   #901