Python的生成器和生成器表达式
一,生成器和生成器表达式
什么是生成器,生成器实质就是迭代器,在python中有三种方式来获取生成器:
1. 通过生成器函数
和普通函数没有区别,里面有yield的函数就是生成器函数,生成器函数在执行的时候.,默认不会执行函数体.,返回生成器通过生成器的__next__()分段执行这个函数
send() 给上一个yield传值, 不能再开头(没有上一个yield), 最后一个yield也不可以用send()
先来看一下简单的函数
def xue(): #创建一个函数
print('学')
return 'Python' #生成器
xue1 = xue()
print(xue1)
结果:
学
Python
函数中的return换成yield这就是一个生成器
def xue():
print('学')
yield 'Python'
xue1 = xue()
print(xue1)
结果:
<generator object xue at 0x000002B7F1115660>
运行结果跟上面的不一样,因为由于函数中存在yield,那么这个函数就是一个生成器函数,这个时候我们在执行这个函数的时候,就不再是函数的执行了,而是获取这个生成器,如何使用呢?想想迭代器,生成器的本质就是迭代器,所以,我们可以直接执行__next__()来执行以下生成器
def xue():
print('学')
yield 'Python'
xue1 = xue() #这时候函数不会执行,而是获取到生成器
YJ = xue1.__next__()#这个时候函数才会执⾏行yield的作⽤用和return一样. 也是返回数据
print(YJ)
结果:
学
Python
yield和return的区别就是,yield是分段来执行一个函数,return是直接停止执行函数
def xue():
print('学')
yield 'Python'
print('也学')
yield 'java'
xue1 = xue() #这时候函数不会执行,而是获取到生成器
YJ = xue1.__next__()
print(YJ)
YJ1 = xue1.__next__()
print(YJ1)
YJ2 = xue1.__next__() #最后一个yield执行完毕,再次__next__()程序报错,也就是说和return无关了
print(YJ2)
结果:
当程序运行完最后一个yield,那么后面继续进行__next__()
需求:某学校要订购50000套校服,工厂直接生产50000套校服,但是学校也没有5000个学生,也没有教室放置一次性生产那么多,最后的效果会是什么呢?直接生产50000件校服,刷一下量大的话把你内存撑满!!!
def xiaofu():
lst = []
for el in range(0,50000):
lst.append('校服'+str(el))
return lst
xiaofu()
print(xiaofu())
我要一套你给一套,一共50000,是不是很完美
def xiaofu():
for el in range(0,50000):
yield '校服'+str(i)
xf = xiaofu()
print(xf.__next__())
print(xf.__next__())
print(xf.__next__())
print(xf.__next__())
两者的区别,第一种是直接一次性全部拿出来,会很占用内存,第二种是使用生成器,一次就一个,用多少生产多少,直到生产完,生成器是一个一个的指向下一个,不会回去,__next__()到哪,指针就指到哪儿,下一次继续获取指针指向的值
send方法,send和__next__()一样都可以让生成器执行到下一个yield
def xue():
print('要学')
a = yield 'Python'
print('a=',a)
b = yield 'java'
print('b=', b)
c = yield 'PHP'
print('c=', c)
yield 'YJ加油!'
xue1 = xue() #获取生成器
fh = xue1.__next__()
print(fh)
#结果:要学
# Python
fh1 = xue1.send('VB')
print(fh1)
# 结果:a= VB
# java
fh2 = xue1.send('C#')
print(fh2)
# 结果:b= C#
# PHP
fh3 = xue1.send('C++')
print(fh3)
# 结果:c= C++
# YJ加油!
send和__next__()的区别
1.send和next()都是让生成器向下走一次
2.send可以给上一个yield的位置传递值,不能给最后一个yield发送值,在第一次执行生成器代码的时候不能使用send()
生成器可以使用for需变换来循环获取内部元素:
def xue():
print('要学')
a = yield 'Python'
print('a=',a)
b = yield 'java'
print('b=', b)
c = yield 'PHP'
print('c=', c)
yield 'YJ加油!'
xue1 = xue()
for el in xue1:
print(el)
结果:
2. 通过各种推导式来实现生成器
1. 列表推导式 [结果 for循环 条件筛选]
2. 字典推导式 {k:v for循环 条件筛选}
3. 集合推导式 {k for循环 条件}
3. 通过数据的转换也可以获取生成器
二.,生成器表达式,列表推导式,以及其他推导式
我们来看一段代码,给出一个空列表,通过for循环向列表添加1-15个数字:
lst = []
for i in ramge(,):
lst.append(i)
print(lst)
结果:[, , , , , , , , , , , , , ,]
列表推导式写法:
#推导式
lst = [i for i in range(,)]
print(lst)
结果:[, , , , , , , , , , , , , , ]
两者的结果是不是一样?列表推导式比较简洁,列表推导式是通过一行来构建你要的列表,列表推导式看起来代码简单,但是出现错误之后就很难排查
列表推导式的写法:[结果 for 变量 in 可迭代对象]
需求:从1-19岁写入到lst列表中
lst = [str(i)+'岁' for i in range(,)]
print(lst)
结果:['1岁', '2岁', '3岁', '4岁', '5岁', '6岁', '7岁', '8岁', '9岁', '10岁', '11岁', '12岁', '13岁', '14岁', '15岁', '16岁', '17岁', '18岁', '19岁']
我们还可以对列表中的数据进行筛选,筛选写法:
[ 结果 for 变量 in 可迭代对象 if 条件 ]
#获取1-100内所有的偶数
lst = [i for i in range(1,100) if i % 2 ==0]
print(lst)
生成器表达式和列表推导式的语法基本是一样的,只是把[]换成()
YJ = (i for i in range(1,15))
print(YJ)
结果为:
<generator object <genexpr> at 0x000002CE3ABA5660>
上面的结果就是一个生成器,我们可以使用for循环来获取这个生成器
YJ = ('我今年%s岁了' % i for i in range(20))
for i in YJ:
print(i)
结果:
我今年0岁了
我今年1岁了
我今年2岁了
我今年3岁了
我今年4岁了
我今年5岁了
我今年6岁了
我今年7岁了
我今年8岁了
我今年9岁了
我今年10岁了
我今年11岁了
我今年12岁了
我今年13岁了
我今年14岁了
我今年15岁了
我今年16岁了
我今年17岁了
我今年18岁了
我今年19岁了
生成器表达式也是可以进行筛选的
获取1-100内能被3整除的数
# 获取1-100内能被3整除的数
YJ = (i for i in range(1,100) if i % 3 == 0)
print(YJ)
#结果:<generator object <genexpr> at 0x000002164AC95660>
for i in YJ: #使用for循环来循环这个生成器拿结果
print(i)
结果;
3,6,9,12,15...99
100以内能被3整除的数的平方
YJ = (i * i for i in range(100) if i % 3 == 0)
for i in YJ: #使用for循环来循环这个生成器拿结果
print(i)
生成器表达式跟列表推导式的区别:
1.列表推导式比较耗内存,一次性加载,生成器表达式几乎不占内存,使用的时候才分配和使用内存
2.得到的值不一样,列表推导式得到的是一个列表,生成器表达式获取的是一个生成器
生成器有惰性机制,生成器只有访问的时候才取值,说白了,你找它要它才会给你值,不找不给它也不会执行
字典推导式:
根据名字也能猜到,推到出来的是字典
dic = {'a' : 1, 'b' : 2, 'c' : 3}
dic1 = {dic[key] : key for key in dic}
print(dic1)
#结果:{1: 'a', 2: 'b', 3: 'c'}
集合推导式:
集合推导式可以帮我们直接生成一个集合,集合的特点是无序,不重复,所有集合推导式自带去重功能
lst = [1,1,2,3,3,66,66,8,9]
a = {abs(i) for i in lst}
print(a)
#结果:{1, 2, 3, 66, 8, 9}
总结:推导式有,列表推导式,字典推导式,集合推导式,切记切记!!!元组是没有推导式的
生成器表达式:(结果 for 变量量 in 可迭代对象 if 条件筛选)
生成器表达式可以直接获取到生成器对象,生成器对象可以直接进行for循环,生成器具有惰性机制!!!
2019年11月13日
Python的生成器和生成器表达式的更多相关文章
- python day12 ——1.生成器2.生成器表达式 3.列表推导式
一.生成器 什么是生成器. 生成器实质就是迭代器. 在python中有三种方式来获取生成器: 1. 通过生成器函数. 2. 通过各种推导式来实现生成器 . 3. 通过数据的转换也可以获取生成器. 1. ...
- Python学习笔记(4):容器、迭代对象、迭代器、生成器、生成器表达式
在了解Python的数据结构时,容器(container).可迭代对象(iterable).迭代器(iterator).生成器(generator).列表/集合/字典推导式(list,set,dict ...
- python全栈开发-前方高能-生成器和生成器表达式
python_day_13 今日主要内容1. 生成器和生成器函数生成器的本质就是迭代器生成器的三种创建办法: 1.通过生成器函数 2.通过生成器表达式创建生成器 3.通过数据转换 生成器函数: 函数中 ...
- Python入门-生成器和生成器表达式
昨天我们说了迭代器,那么和今天说的生成器是什么关系呢? 一.生成器 什么是生成器?说白了生成器的本质就是迭代器. 在Python中中有三种方式来获取生成器. 1.通过生成器函数 2.通过各种推导式来实 ...
- python 可迭代对象,迭代器和生成器,lambda表达式
分页查找 #5.随意写一个20行以上的文件(divmod) # 运行程序,先将内容读到内存中,用列表存储. # l = [] # 提示:一共有多少页 # 接收用户输入页码,每页5条,仅输出当页的内容 ...
- python的迭代器、生成器、三元运算、列表解析、生成器表达式
一 迭代的概念 迭代是Python最强大的功能之一,是访问集合元素的一种方式. 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前 ...
- 2018.8.13 python中生成器和生成器表达式
主要内容: 1.生成器和生成器函数 2.列表推导式 一.生成器 生成器是指就是迭代器,在python中有三种方式来获取生成器: 1.通过生成器函数 2.通过各种推导式来实现生成器 3.通过数据的转换也 ...
- python之序列去重以及生成器、生成器函数、生成器表达式与迭代器浅谈
首先要明确序列值类型是否可哈希,因为可哈希的值很简单就可以用 in /not in 写个生成器去判断,如果是不可哈希的就要去转换为可哈希的再用 in/not in 去判断 原地不可变类型(可哈希): ...
- python基础之生成器,三元表达式,列表生产式
生成器 1.什么是生成器? 在函数内但凡出现yield关键字,再调用函数就不会执行函数体代码,会返回一个值,该值称为生成器. 生成器的本质就是迭代器. 2.为什么要用生成器? 生成器是一种自定义迭代器 ...
随机推荐
- pv操作与信号量详解
对于信号量,可以认为是一个仓库,有两个概念,容量和当前的货物个数. P操作从仓库拿货,如果仓库中没有货,线程一直等待,直到V操作,往仓库里添加了货物,为了避免P操作一直等待下去,会有一个超时时间. V ...
- 2016/09/29 SQL中的join
1.建表 首先建tb_a并插入数据. )); insertinto tb_a(symbol, sname) values ('A','B'); insertinto tb_a(symbol, snam ...
- express 中间件的简单应用与实现
express 中间件的简单应用与实现 看了慕课网双越老师的课之后结合自己的理解做了一些简单的总结,如有不恰当之处,欢迎指正. 提到 express 就不得不提到中间件,接下来就简单的介绍一下 exp ...
- LeetCode 11月第2周题目汇总
开源地址:点击该链接 前言 最近比较忙,这周几乎没有刷题,只刷了6道题~ 题目汇总 0387_first_unique_character_in_a_string类似的题目比较多了,字符串中找出特别的 ...
- Nginx配置实例-反向代理实例:根据访问的路径跳转到不同端口的服务中
场景 Ubuntu Server 16.04 LTS上怎样安装下载安装Nginx并启动: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/detai ...
- javascript中引用传递的问题如何解决
我们有时候会向一个方法中传入一个参数,并且对这个参数做一些处理的操作: 但是因为是引用传递,处理过后会对原有的对象造成修改,无法进行反复使用. 如例子: 两次打印的结果一模一样.这样下一个方法在继续使 ...
- Odoo系统有哪些不同版本?
来源:www.odooyun.com 1. Odoo10.0 vs Odoo11.0 vs 8.0 截至2017年底,最新的Odoo发布版为Odoo 11.0,但功能上有一定精简(去除财务模块,去除工 ...
- 深度学习优质学习项目大放送!-AI Studio精选开源项目合集推荐
近期 在AI Studio上发现了不少优质的开源深度学习项目,从深度学习入门到进阶,涵盖了CV.NLP.生成对抗网络.强化学习多个研究方向,还有最新的动态图,都以NoteBook的方式直接开源出来,并 ...
- 汇编 易混淆指令lea offset
lea 是机器指令,offset 是伪指令. LEA BX, BUFFER ;在实际执行时才会将变量buffer的地址放入bx MOV BX, OFFSET BUFFER ;在编译时就已经计算出buf ...
- TortoiseGit 保存账号密码
TortoiseGit下载网址:http://download.tortoisegit.org/tgit/ 修改.gitconfig .gitconfig 用于记录git配置信息 路径:系统盘:\Us ...