生成器是一类特殊的迭代器(既然是迭代器了,那么当然就是可迭代对象).自己就是.不需要写__iter__(),__next__()这两个方法.
自己天生就是迭代器.
仍然可以使用iter(),next() 方法.
分类:
列表推导式[]: ---> () 就是 生成器表达式 :():<generator:>
生成器里面存放的不是具体的数据,只是存放的是一个算法.
生成器表达式和列表推导式的异同:
不同: (表达式) [表达式]
-------------------|----------------------|---------------------
产生的对象 生成器对象 列表对象
占用内存 少 多
-------------------|----------------------|---------------------
相同: 使用结果一致
方式1:生成器表达式 列表推导式的[] 换成()之后就是生成器
首先要理解 列表推推导式 --> 返回值是一个列表
方式2:生成器函数 含有yield 关键字
def fib(n): num1, num2 = 1, 1 count = 0 # 1.暂时挂起当前函数 将后面的值返回给调用生成器的地方 yield 100 # 返回值 # 2.当再次调用生成器函数的时候, 会恢复当前函数继续执行 yield 101 # 返回值 if __name__ == '__main__': # 生成器函数调用 不会执行函数代码 唯一的目的就是:产生生成器对象 f = fib(10) # 调用生成器<迭代器>,获取下一个元素的值 print(next(f)) print(next(f)) # 断点调试只适用于少量代码的时候,多的时候不管用
生成器计算斐波拉契:
def fib(n): num1, num2 = 1, 1 count = 0 while count < n: yield num1 # 可以返回多个值 yield 1,2,3 count += 1 num1, num2 = num2, num1 + num2 return 1000 # 最后不需要raise StopIteration <生成器内部已经自动实现> # 一般在生成器中不使用return关键字,一旦使用就会结束生成器的迭代过程 if __name__ == '__main__': f = fib(10) # for i in f: 可以取出多个值 for i,j in f:... # print(i) # 如果需要获取生成器函数的最终返回值,需要捕获迭代的异常 # while True: # # 通过迭代器取出下一个元素的值<返回值> # try: # pass # except Exception as e: # print(e) # break # else: # print(i) """send()唤醒生成器,可以传参数"""
send在唤醒生成器的时候传入参数:
""" 面试问: yield的作用: send()可以传参数,不能第一次使用 使用场景:在生成下一个的时候,从我 指定的位置<传入的参数>开始生成 通过传入的参数,控制生成器下一次生成的元素 """ """ 唤醒生成器: 元素的值=next(生成器对象) 元素的值=生成器.send(数据) 异同: next是函数 send()是方法 next不能传参数,send可以传入参数<通过传输不同的参数控制生成器执行的逻辑> 第一次只能next,其余地方随意使用<参数的值只有yield可以接收,因为第一次的时候没有yield> 同: 获取到下一个元素的值<迭代> yield关键字作用: 1.挂起当前函数代码,将后面的表达式返回,调用生成器的地方 2.接收可能存在的参数,紧接着上次执行的地方继续往下执行 """ def fib(n): num1, num2 = 1, 1 count = 0 while count < n: # send()发送的消息只有yield关键字才能接收 ret = yield num1 print('接收到的参数是:', ret) count += 1 num1, num2 = num2, num1 + num2 if __name__ == '__main__': f = fib(10) # 在第一次调用生成器的时候必须使用next(),因为第一次的时候没有yield接收传入的参数 # TypeError: can't send non-None value to a just-started generator # 意思就是不能在第一次的时候将非None的数据发送给生成器. # print(f.send(None)) 这样就可以 print(next(f)) print(f.send(101)) print(f.send(102)) print(f.send(103)) print(f.send(103)) print(f.send(103)) """ 容器类型就是典型的可迭代对象. 典型的:意思就是通用的,肯定是,具有代表性的 生成器肯定是可迭代对象.反之不行 """