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.为什么要用生成器? 生成器是一种自定义迭代器 ...
随机推荐
- 深入学习CSS3-flexbox布局
学习博客:https://css-tricks.com/snippets/css/a-guide-to-flexbox/ 学习博客:http://caibaojian.com/demo/flexbox ...
- MarkDown快速入门(typora)
MarkDown快速入门(typora) 1.代码块: //代码块语法: ```java ```shell 1.java代码 package com.yjx.jdbc import java.sq ...
- IDEA+Maven 整合SSM框架实现简单的增删改查(新手入门,傻瓜操作)
原博客地址:https://blog.csdn.net/khxu666/article/details/79851070 选用SSM框架的原因在目前的企业级Java应用中,Spring框架是必须的.S ...
- NodeJS4-2静态资源服务器实战_实现获取文件路径
实例2 : 实现获取文件路径,判断是文件还是文件夹,如果是文件夹就显示里面的列表文件,如果是文件就显示里面的内容 defaultConfig.js module.exports={ root:proc ...
- Github挂载大文件解决方案
正常情况下,我们上传代码之类的文本文件,都不会太大,可以直接通过[Upload Files]选项直接上传. 但是这样的操作仅限文件大小在25MB以内. 如果你选择的文件超过25MB,那么Github会 ...
- 一起学Vue之计算属性和侦听器
概述 在Vue开发中,模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的.在模板中放入太多的逻辑会让模板过重且难以维护.当你想要在模板中多次引用相同表达式时,就会更加难以处理.所以,对于任何复 ...
- Java多线程面试问答
今天,我们将讨论Java 多线程面试问答. 线程是Java面试问题中的热门话题之一.在这里,我从面试的角度列出了大多数重要的Java多线程面试问题,但是您应该对Java线程有足够的知识来处理后续问题. ...
- MySQL数据篇 (一)存储过程实现简单的数据修改及事务的使用
1.需求,手动给会员新增京币,并且添加分配日志,返回修改是否成功 CREATE DEFINER=`jszapi`@`%` PROCEDURE `p_allot_user_coin`(IN `_memb ...
- Android组件体系之BroadcastReceiver小结
1.常见分类 BroadCastReceiver,按注册方式可以分为静态广播接收器和动态广播接收器. 静态广播接收器:不受程序是否启动的约束,当应用程序关闭之后,还是可以接收到广播(一般广 ...
- 用 Keras 实现单词级的 one-hot 编码 & 使用散列技巧的单词级的 one-hot 编码
from keras.preprocessing.text import Tokenizer samples = ['The cat sat on the mat.', 'The dog ate my ...