python之生成器和列表推导式
一、生成器函数
1、生成器
就是自己用python代码写的迭代器,生成器的本质就是迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)。
2、构建生成器的两种方式
1,生成器函数:跟常规函数定义类似,但是,使用yield语句而不是return语句返回结果。
yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。
2,生成器表达式:类似于列表推导,但是,返回的是生成器的一个对象,
而不是一次构建一个结果列表。
3、生成器函数
3-1、先看一般的函数
def func1(x):
x += 1
return x
func1(5) #函数的执行命令,并且接收函数的返回值。
print(func1(5)) #
3-2、再看生成器函数
def func1(x):
x += 1
print(666)
yield x
x +=2
print(777)
print(x)
yield 'xiaobai'
x +=3 g = func1(5) # 此时的func1(5)不会执行函数,因为它只是生成器函数对象
print(g) # <generator object func1 at 0x0000025E5D618780>
print(g.__next__()) #666 6
print(next(g)) #777 8 xiaobai
3-3、yield与return的区别
return:结束函数,给函数的执行者返回值
yield:不会结束函数,一个next对应一个yield,
执行yield上面的代码并给 生成器对象.__next__() 返回值
3-4、生成器函数与迭代器的区别
区别1:自定制的区别
迭代器由可迭代对象转化而来,已经‘写死了’
l1 = [1,2,3,4,5]
l1.__iter__()
生成器可用自定制函数来定制
def func1(x):
x += 1
yield x
x += 3
yield x
x += 5
yield x
g1 = func1(5)
print(g1.__next__())
print(g1.__next__())
print(g1.__next__())
区别2:内存级别的区别。
迭代器是需要可迭代对象进行转化,可迭代对象非常占内存。
生成器直接创建,不需要转化,从本质就节省内存。
def func1():
for i in range(1000000):
yield i
g1 = func1()
for i in range(50):
print(g1.__next__()) #一个next取一次值,可用for循环取值
3-5、send与next
先看例子:
def func1():
print(1)
count = yield 6 print(count)
print(2)
count1 = yield 7 print(count1)
print(3)
yield 8 g = func1()
print(g.__next__()) #1 6
print(g.send('xiaobai')) #xiaobai 2 7
print(g.send('xiaigou')) #xiaogou 3 8
总结:
send与next一样,也是对生成器取值(执行一个yield)的方法。
send可以给上一个yield 传值。
注意小坑:
1,第一次取值只能用next
2,最后一个yield不可能得到send传的值
3-6、生成器close()方法
def fun():
for i in range(5):
yield i
g = fun()
print(g.__next__())
print(g.__next__())
print(g.__next__())
g.close() # 直接把生成器的值取(删)完了,后面就不能再取值
print(g.__next__()) # 报错 a = (i for i in range(4))
print(a.__next__())
print(a.__next__())
a.close()
print(a.__next__()) #报错
3-7、生成器函数的应用例子
要制作一批量很大的衣服,用普通的函数只能一次全部制作完:
def cloth1(n):
for i in range(n+1):
print('衣服%s号' % i)
cloth1(100000) #一次全部制作完了
而用生成器函数,需要制作多少就先制作多少:
def cloth2(n):
for i in range(1,n+1):
yield '衣服%s号' % i
g = cloth2(10000) 先制作50件:
for i in range(50):
print(g.__next__()) #衣服1号,衣服2号,衣服3号...衣服50号 再制作50件:
for i in range(50):
print(g.__next__()) #衣服51号,衣服52号,衣服53号...衣服100号
3-8、生成器的取值方式
def func1():
for i in range(50):
yield i g1 = func1() # 生成器对象 # 方式一:一个next取一次值
for i in range(40):
print(g1.__next__()) # 0-39 # 方式二:直接循环生成器对象,把生成器全部内容一条条输出
for i in g1:
print(i) # 0-49
二、列表推导式,生成器表达式
1、普通方法创建一个元素为1到100的列表
l1 = []
for num in range(1,101):
l1.append(num)
print(l1)
2、列表推导式:一行代码几乎搞定你需要的任何的列表
2-1、两种方式:
循环模式
筛选模式
2-2、循环模式:[变量(加工后的变量) for 变量 in iterable]
#1到100的列表
l = [i for i in range(1,101)]
print(l) #[1,2,3,4...100] #python1到python15的列表
l2 = ['python%s' % i for i in range(1,16)]
print(l2) #[python1,python2,python3...python15,] #1到10的平方
l3 = [i*i for i in range(1,11)]
print(l3) #[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
2-3、筛选模式 [变量(加工后的变量) for 变量 in iterable if 条件]
#30以内的偶数
l4 = [i for i in range(1,31) if i % 2 == 0]
print(l4) #[2, 4, 6, 8,10,...28, 30] #30以内能被3整除的数
l5 = [i for i in range(1,31) if i % 3 == 0]
print(l5) #[3, 6, 9, 12, 15, 18, 21, 24, 27, 30] #30以内能被3整除的数的平方
l6 = [i**2 for i in range(1,31) if i % 3 == 0]
print(l6) #[9, 36, 81, 144, 225, 324, 441, 576, 729, 900] #找出列表中含有两个'e'的元素
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
l7 = [j for i in names for j in i if j.count('e') == 2]
print(l7) #['Jefferson', 'Wesley', 'Steven', 'Jennifer']
2-4、列表推导式优缺点
优点:一行解决,方便。
缺点:容易着迷,不易排错,不能超过三次循环。
列表推导式不能解决所有列表的问题,所以不要太刻意用。
3、生成器表达式:将列表推导式的[]换成()即可
g = (i for i in range(100000000000))
print(g) #生成器表达式左边的变量g是生成器对象
print(g.__next__()) #
print(g.__next__()) #
print(g.__next__()) # 上面代码相当于:
def func():
for i in range(100000000000):
yield i
g = func() #生成器对象
print(g.__next__())
print(g.__next__())
print(g.__next__())
4、扩展
4-1、字典推导式
# 例一:将一个字典的key和value对调
dic = {'a': 10, 'b': 34}
new_dic = {dic[k]: k for k in dic}
print(new_dic)
# 结果:
# {10: 'a', 34: 'b'} # 例二:合并大小写对应的value值,将k统一成小写
dic = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
new_dic = {k.lower():dic.get(k.lower(),0) + dic.get(k.upper(),0) for k in dic}
print(new_dic)
# 结果:
# {'a': 17, 'b': 34, 'z': 3}
4-2、集合推导式
# 例一:计算列表中每个值的平方,自带去重功能
set1 = {x**2 for x in [1, -1, 2]}
print(set1)
# 结果:
# {1, 4}
4-3、集合推导式和字典推导式的区别
相同点:外层都是使用大括号{}
不同点:返回的形式是 key:values 形式的就是字典,返回的形式是 values1,values2...形式的是集合
# 集合推导式
set1 = {x**2 for x in (1, -1, 2)}
print(set1,type(set1)) # {1, 4} <class 'set'> # 字典推导式
dic1 = {x**2:x for x in (1, -1, 2)}
print(dic1,type(dic1)) # {1: -1, 4: 2} <class 'dict'>
4-4、练习题
# 例1: 过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
l1 = [i.upper() for i in ['asdf','a','b','qwe'] if len(i) >= 3]
print(l1)
# 结果:
# ['ASDF', 'QWE'] # 例2: 求(x,y)其中x是0-5之间的偶数,y是0-5之间的奇数组成的元组列表
l2 = [(x,y) for x in range(6) if x % 2 ==0 for y in range(6) if y % 2 == 1]
print(l2)
# 结果:
# [(0, 1), (0, 3), (0, 5), (2, 1), (2, 3), (2, 5), (4, 1), (4, 3), (4, 5)] # 例3: 求M中3,6,9组成的列表
M = [[1,2,3],[4,5,6,24,3],[7,8,9,12,9]]
l3 = [j for i in M for j in i for z in [3,6,9] if j / z == 1 ]
print(l3)
# 结果:
# [3, 6, 3, 9, 9]
python之生成器和列表推导式的更多相关文章
- 《Python》 生成器和列表推导式
一.初识生成器: 生成器就是自己用Python代码写的迭代器,生成器的本质就是迭代器. 1.Python中提供的生成器: 1.生成器函数: 使用yield语句而不是return语句返回结果.yield ...
- python之生成器(~函数,列表推导式,生成器表达式)
一.生成器 概念:生成器的是实质就是迭代器 1.生成器的贴点和迭代器一样,取值方式也和迭代器一样. 2.生成器一般由生成器函数或者声称其表达式来创建,生成器其实就是手写的迭代器. 3.在python中 ...
- Python进阶(四)----生成器、列表推导式、生成器推导式、匿名函数和内置函数
Python进阶(四)----生成器.列表推导式.生成器推导式.匿名函数和内置函数 一丶生成器 本质: 就是迭代器 生成器产生的方式: 1.生成器函数
- Python-02 生成器表达式,列表推导式
列表推导式和生成器表达式 列表推导式,生成器表达式1,列表推导式比较直观,占内存2,生成器表达式不容易看出内容,省内存. [ 变量(加工后的数据) for 变量i in 可迭代的数据类型 ] 列表 ...
- python全栈开发day13-迭代器、生成器、列表推导式等
昨日内容:函数的有用信息.带参数的装饰器.多个装饰器修饰一个函数 迭代器 可迭代对象:内部含有__iter__方法 迭代器 定义:可迭代对象.__iter__()就是迭代器,含有__iter__且__ ...
- python基础学习Day12 生成器、列表推导式、字典的表达式、字典键值对的互换、集合推导式
一.生成器 1.1 生成器:就是(python)自己用代码写的迭代器,生成器的本质就是迭代器. 1.2 生成器函数 def func1(x): x += print() yield x print() ...
- python基础(14):生成器、列表推导式
1. 生成器 什么是⽣成器?⽣成器实质就是迭代器. 在python中有三种⽅式来获取⽣成器: 1. 通过⽣成器函数 2. 通过各种推导式来实现⽣成器 3. 通过数据的转换也可以获取⽣成器 ⾸先,我们先 ...
- 【python】 迭代器、生成器、列表推导式
一.可迭代对象.迭代器 1.可以被for循环的数据类型(可迭代对象): 字符串(str).列表(list).字典(dict).元祖(tuple).range() 2.迭代器 2.1 将可迭代对象==& ...
- python基础之生成器,生成器函数,列表推导式
内容梗概: 1. 生成器和生成器函数. 2. 列表推导式. 1.生成器函数1.1 生成器函数. 就是把return换成yield def gen(): print("爽歪歪") y ...
随机推荐
- 林业有害生物监测系统(重庆宇创GIS)
本文由重庆宇创GIS团队原创,转载请注明来源http://www.cnblogs.com/ycdigit/p/8916073.html 一.概述 林业有害生物监测信息平台(森林病虫害监测预警系统) ...
- 动态BGP和静态BGP的含义与区别
1.在华为云上选购虚拟机时,会让用户选择动态BGP还是静态BGP, 全动态BGP可根据设定的寻路协议第一时间自动优化网络结构,以保持客户使用的网络持续稳定.高效. 静态BGP中的网络结构发生变化,运营 ...
- Linux压缩打包tar命令总结
命令简介 在Linux系统的维护.管理中,tar命令是一个使用频率很高的命令,tar命令的功能主要是将众多文件打包成一个tar文件并压缩,并且能保持文件的权限属性.tar其实最开始是用来做磁带 ...
- AjaxPro2完整入门教程
一.目录 简单类型数据传送(介绍缓存,访问Session等) 表类型数据传送 数组类型数据传送(包含自定义类型数据) 二.环境搭建 1.这里本人用的是VS2012. 2.新建一个空的Web项目(.NE ...
- 图解slub
1.前言 在Linux中,伙伴系统(buddy system)是以页为单位管理和分配内存.但是现实的需求却以字节为单位,假如我们需要申请20Bytes,总不能分配一页吧!那岂不是严重浪费内存.那么该如 ...
- c/c++ 多线程 利用条件变量实现线程安全的队列
多线程 利用条件变量实现线程安全的队列 背景:标准STL库的队列queue是线程不安全的. 利用条件变量(Condition variable)简单实现一个线程安全的队列. 代码: #include ...
- Cs231n课堂内容记录-Lecture 7 神经网络训练2
Lecture 7 Training Neural Networks 2 课堂笔记参见:https://zhuanlan.zhihu.com/p/21560667?refer=intelligent ...
- Win10 Service'MongoDB Server' failed to start. Verify that you have sufficient privileges to start system services【简记】
最近工作中有需要用到 MongoDB数据库,以前用的3.*的版本,这次用的是较新4.0.6的版本,然后去官网下载安装. 安装到一半,就弹出如下提示,说是"MongoDB Server&quo ...
- LeetCode算法题-Longest Continuous Increasing Subsequence(Java实现)
这是悦乐书的第286次更新,第303篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第154题(顺位题号是674).给定未排序的整数数组,找到最长连续增加子序列的长度.例如 ...
- LeetCode算法题-Max Consecutive Ones(Java实现)
这是悦乐书的第242次更新,第255篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第109题(顺位题号是485).给定二进制数组,找到此数组中连续1的最大数量.例如: 输 ...