生成器
# 首先必须区分迭代器(Iterator)和可迭代对象(Iterable) """ 1、可迭代对象(Iterable): 一类是集合数据类型,如 list 、 tuple 、 dict 、 set 、 str 等; 一类是生成器对象,包括生成器和带 yield 的generator function。 可迭代对象可以使用for循环遍历 2、迭代器(Iterator): 可以被next()函数调用并不断返回下一个值的对象称为迭代器对象。 3、生成器对象是迭代器对象,可迭代对象不一定是迭代器对象 4、可以使用iter()函数将可迭代对象转为迭代器对象 """ # 为什么有了列表生成式,还需要生成器呢?当我们使用列表生成式,list = [x for x in range(100000000)]时 # 还能得到一个正确的list吗?不能!!一次性生成了100000000个数,这些数把内存空间都占满了,程序还怎么运行啊! # 所以生成器就是为了解决这么一个事而出现的。 # 生成器是什么? # 生成器里面存放的是生成数字的一套规则(算法),返回的是一个生成器对象,假如我们同样要100000000个数 # 生成器只存放生成这100000000个数的规则,当我们要取时,我就去拿,要拿多少由你定。 # 创建生成器方法一 # 第一种方法很简单,只要把一个列表生成式的 [ ] 改成 ( ) # 返回的list并不是一个列表,更不是一个元组,而是一个生成器对象 # 生成器保存的是算法,每次调用 next(G) ,就计算出 G 的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出 StopIteration 的异常 list = (x for x in range(10)) print(next(list), end="\t") # 既然生成器也是可迭代对象,那么肯定也是可以使用for循环遍历的 for x in list: print(x, end="\t") print() print("*" * 60) # 创建生成器方法二 # 带 yield 的 generator function # 下面定义了斐波拉契数列的推算规则 def fib(times): n = 0 a, b = 0, 1 print("8888") while n < times: print("-----1-----") t = yield b print("-----2-----") a, b = b, a + b n += 1 F = fib(3) print(next(F)) print(next(F)) print(next(F)) print("*" * 60) # 让我们来理解一下上面那个程序,yield 到底是什么? # F = fib(3) 这里是创建一个生成器对象F # print(next(F)) next(F)才开始正式调用生成器的function # 注意:遇到yield时,马上停止!!!程序不往下面走了,所以第一个next(F)只输出了888和-----1------ # 注意:next(F)有一个返回值,返回的值时yield后面的b # 第二个next(F),从第一次停止的地方开始,所以不会在输出888了,输出-----2-----和-----1----- # __next()__ # 使用__next()__方法也可以去除生成器中的值,和next(F)的效果是一样的 def fib(times): n = 0 a, b = 0, 1 print("8888") while n < times: print("-----1-----") t = yield b print("-----2-----") a, b = b, a + b n += 1 F = fib(3) print(F.__next__()) print(F.__next__()) print(F.send("haha")) print("*" * 60) # send() def fib(times): n = 0 while n < times: temp = yield n print(temp) n += 1 F = fib(3) print(next(F)) print(next(F)) print(F.send("haha")) # 我们可以看到yield n这个整体会返回一个数给temp,未经过处理返回的数是None # 我们可以F.send("haha"),这样yield n这个整理就会把发送的haha赋值给temp # 注意:c.__next__()等价c.send(None),所以也要小心 StopIteration 异常 # 注意:第一次不能使用c.send("haha"),为什么呢?第一次你发送haha,但是程序第一次遇到yield的时候就停了,haha给谁呢? # 所以第一次不能使用c.send("haha"),解决方法:使用c.send(None)或者使用c.__next__()