第十三天 生成器和生成器函数, 列表推导式
一.生成器
生成器Generator:
本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)
特点:惰性运算,开发者自定义
python中提供的生成器:
1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行
2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
python中有三种方式来获取生成器的:
1. 通过生成器函数
2. 通过各种推导式来实现生成器
3. 通过数据的转换也可以获取生成器
yield和return的效果是一样的. 但yield是分段来执行一个函数. 而return直接停止执行函数
由于函数中存在了yield. 那么这个函数就是一个生成器函数. 这个时候. 我们再执行这个函数的时候. 就不再是函数的执行了. 而是获取这个生成器.如何使用呢? 想想迭代器. 生成器的本质是迭代器. 所以. 我们可以直接执行__next__()来执行以下生成器.
当程序运行完最后一个yield. 那么后面继续进行__next__()程序会报错
生成器的作用:节省内存
区别: 第一种是直接一次性全部拿出来. 会很占⽤用内存.第二种使用生成器. 一次就一个. 用多少生成多少. 生成器是一个一个的指向下一个. 不会回去, __next__()到哪, 指针就指到哪儿.下一次继续获取指针指向的值.
Send()方法:
send和__next__()一样都可以让生成器执行到下一个yield
send 和 __next__()的区别:
1. send和next()都是让生成器向下走一次
2. send可以给上一个yield的位置传递值, 不能给最后一个yield发送值. 在第一次执行生成器代码的时候不能使用send(),必须要用__next__()获取一下值
使用send的注意事项
1. 第一次使用生成器的时候 是用next获取下一个值
2. 最后一个yield不能接受外部的值
生成器可以使用for循环获取内部元素:
二.列表推导式,生成器表达式以及其他推导式
列表推导式
列表推导式,最终给你的式列表
列表推导式常用语法:
[最终结果(变量) for 变量 in 可迭代对象]
示例:生成列表,里面装1-14的数据
注意:
列表推导式是通过一行来构建你要的列表, 列表推导式看起来代码简单. 但是出现错误之后很难排查.
筛选模式
[结果 for 变量 in 可迭代对象 if条件]
生成器表达式:
生成器表达式和列表推导式的语法基本上是一样的. 只是把[]替换成()。
打印的结果就是一个生成器. 我们可以使用for循环来循环这个生成器
示例:
生成器表达式也可以进行筛选
生成器表达式和列表推导式的区别:
1. 列表推导式比较耗内存. 一次性加载. 生成器表达式几乎不占用内存. 使用的时候才分配和使用内存
2. 得到的值不一样. 列表推导式得到的是一个列表. 生成器表达式获取的是一个生成器.
举个例子:同样一篮子鸡蛋.
列表推导式: 直接拿到一篮⼦鸡蛋.
生成器表达式: 拿到一个老母鸡. 需要鸡蛋就给你下鸡蛋
生成器的惰性机制:
生成器只有在访问的时候才取值. 说白了. 你找他要,他才给你值. 不找他要, 他是不会执行的.
深坑 ==》 生成器,要值得时候才拿值
字典推导式:
推导出的是字典
集合推导式:
集合推导式可以帮我们直接生成一个集合. 集合的特点: 无序, 不重复. 所以集合推导式自带去重功能
总结:
推导式有, 列表推导式, 字典推导式, 集合推导式, 没有元组推导式
生成器表达式: (结果 for 变量 in 可迭代对象 if 条件筛选)
生成器表达式可以直接获取到生成器对象. 生成器对象可以直接进行for循环. 生成器具有惰性机制.
面试题(*****)