python (八)迭代器、生成器、列表推导式
一、迭代器
1、先来讲讲什么是可迭代对象
字符串、列表、元组、字典、集合都可以被for循环,说明他们都是可迭代的。
2、怎么判断是不是一个可迭代对象
判定方法:内部含有‘__iter__’方法的数据就是可迭代对象
可迭代对象的种类:list str tuple set dict range() 文件句柄
s1 = '我叫王大锤' print(dir(s1)) # 查看对象S1中变量、方法 print('__iter__' in dir(s1)) # 判断__iter__方法是否在对象S1的所有方法中,存在返回true,不存在返回false
3、怎么判断这个对象是不是迭代器
判定方法:内部含有__iter__方法的并且含有__next__方法的就是迭代器
# 判断是否是迭代器 f1 = open('a.txt', encoding='utf-8') print('__iter__' in dir(f1)) # 判断是否有__iter__方法 print('__next__' in dir(f1)) # 判断是否有__next__方法 f1.close()
迭代器就是在迭代对象的基础上多了个__next__方法。既然这样他们肯定是可以互相转换的
转换方法:
可迭代对象 ----> 迭代器 :可迭代对象 . __next__()
# 循环输出每个元素 # 第一种方法 l1 = [1, 2, 3, '大锤'] # 这是个迭代对象 iter1 = iter(l1) # 这一步也可以用 l1.__iter__() 表示 print(iter1) # 输出iter1的内存地址 print(iter1.__next__()) # 1 print(iter1.__next__()) # 2 print(iter1.__next__()) # 3 print(iter1.__next__()) # 大锤 print(iter1.__next__()) # 超出元素个数,会报错# 第二种方法 l1 = [1, 2, 3, '大锤'] for i in l1: # 循环输出每个元素print(i)# 第三种方法
l1 = [1, 2, 3, '大锤']
for i in l1.__iter__(): # 循环输出每个元素print(i)
4、迭代器的优点
非常非常节省内存:在循环时,同一时刻在内存中只出现一条数据,极大限度的节省了内存
他满足惰性机制:不访问__next__() 就没有值
一次性取值,只能按顺序取
5、为什么要有for循环
为什么要有for循环?
# 利用下表方式循环输出 l = [1, 2, 3, '大锤'] index = 0 while index < len(l):print(l[index])index += 1# 上述方法用下表就可以循环输出,为什么要用迭代器呢?
原因如下:
序列类型字符串:列表,元组都有下标,用上述的方式访问是可以的。
但是非序列类型:字典,集合,文件对象就无法实现了。
for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法,即在遍历之前,先调用对象的__iter__方法将其转换成一个迭代器,然后使用迭代器协议去实现循环访问,这样所有的对象就都可以通过for循环来遍历了
最重要的一点,转化成迭代器,在循环时,同一时刻在内存中只出现一条数据,极大限度的节省了内存~
for循环的优点:
将可迭代对象转化成迭代器;(可迭代对象.__iter__())
利用__next__方法一个一个取值;
利用异常处理终止循环。(不终止,取不到值就会报错)
用while循环模拟for循环:
l1 = [1, 2, 3, '大锤'] iter1 = l1.__iter__() while 1:try:print(iter1.__next__())except StopIteration: # 利用异常处理终止循环break
二、生成器
1、什么是生成器?
在某些情况下,我们也需要节省内存,就只能自己写。我们自己写的这个能实现迭代器功能的东西就叫生成器。
生成器:自己用python代码写的迭代器 本质就是迭代器
2、Python中提供的生成器
生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行
生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
3、生成器函数(函数式写法的生成器)
判定方法:
只要函数中出现yield,那么 他就不是函数了,他是生成器函数。
yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。
# 普通函数 def func1(): # 函数中出现了yield,此函数为生成器函数print(111)print(222)yield 3yield 4yield 5yield 6yield 7 g = func1() # 生成器对象 print(g) # <generator object func1 at 0x10748fa98> 输出的是这个函数的内存地址 print(g.__next__()) # 等同于print(next(g)),输出结果为111 222 3 # 一个next 对应一个 yield print(g.__next__()) # 4 print(g.__next__()) # 5 print(g.__next__()) # 6
# 加了模块的函数 import time # 使用了模块的函数加了yield也是生成器函数 def func():a = 1print('现在定义了a变量')yield ab = 2print('现在又定义了b变量')yield bg1 = func() print('g1 : ', g1) # 打印g1可以发现g1就是一个生成器 print('-'*20) # 我是华丽的分割线 print(next(g1)) # 结果:现在定义了a变量, 收到yield返回的值1 time.sleep(1) # sleep一秒看清执行过程 ,可以看出函数未被yield打断,可以继续执行 print(next(g1)) # 结果:现在定义了变量, 收到yield返回的值2
小总结:
return 结束函数 给函数返回值
yield 不会结束生成器函数,next 对应一个yield进行取值
4、生成器的好处
# 直接for 循环,一次性循环取出所有的值 def cloth():for i in range(1, 201):print('当前被取出来的数是 %s' % (i)) cloth()# yield 返回,每次返回一个值 def cloth1():for i in range(1, 201):yield '当前被取出来的数是 %s' % (i)g = cloth1()for i in range(5):print(g.__next__()) # 只输出1到5 五个数for i in range(195):print(g.__next__()) # 只输出1到195 这几个数
由上面的例子可以看出来,yield可以根据需要取值,能够控制取值的个数,而且不会终止函数
5、send(与__next__类似)
# send 和 __next__的用法和对比 def func(): print(123) # 第三步 content = yield 1 # 第四步将1返回给第二步,即g._# 第六步执行完,yield 1 接print('=======', content) # 第七步 输出 =print(456) # 第八步 输出456 yield 2 #第九步 将值2返回给 g.__next__() g = func() # 第一步 ret = g.__next__() # 第二步 将这个函数转换成迭代器,这是# 第四步执行完,ret接收到的值为 1 # 第九步执行完,ret接收到的值为 2 print('***', ret) # 第五步 输出 *** 1 ret = g.send('hello') # 第六步 给第四步的yield 1 print('***', ret) # 第十步 输出 *** 2
小总结:
send 获取下一个值的效果和next基本一致只是在获取下一个值的时候,给上一yield的位置(例子中的第六步给第四步传了一个值)
使用send的注意事项:
第一次使用生成器的时候 是用next获取
最后一个yield不能接受外部的值
三、列表推导式
1、列表推导式的模式
循环模式: [变量(加工后的变量) for 变量 in iterable]
筛选模式: [变量(加工后的变量) for 变量 in iterable if 条件]
# 循环模式:其实就是for循环的简写,循环输出所有 # 第一种 l1 = [i for i in range(1, 10)] print(l1) # [1, 2, 3, 4, 5, 6, 7, 8, 9] # 第二种 print(['python%s期' % i for i in range(1, 25)])
# 筛选模式 # 第一种 l1 = [i for i in range(10) if i % 2 == 0] print(l1) # [0, 2, 4, 6, 8] # 第二种 # 2.[10以内所有数的平方: 1,4,9,16,.....100] print([i*i for i in range(1, 11)]) # 2.[30以内能被3整除的数的平方:39,36,81....900] print([i**2 for i in range(1, 31) if i % 3 == 0]) # 3.过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母 l1 = ['alex', 'taibai', 'wusir', 're', 'ab'] print([i.upper() for i in l1 if len(i) > 3]) # 4.找到嵌套列表中名字含有两个‘e’的所有名字 # 用列表推导式实现 names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'], ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']] print([name for lst in names for name in lst if name.count('e') >= 2]) # ['Jefferson', 'Wesley', 'Steven', 'Jennifer'] # 用之前的老方法实现 names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'], ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']] l1 = [] for i in names: for i1 in i: if i1.count('e') >= 2: l1.append(i1) print(l1) # ['Jefferson', 'Wesley', 'Steven', 'Jennifer']
2、字典推导式
# 将一个字典的key和value对调 dic = {'a': 10, 'b': 34} dic2 = {dic[k]: k for k in dic} print(dic2) # {10: 'a', 34: 'b'}# 合并大小写对应的value值,将k统一成小写 dic = {'a': 10, 'b': 34, 'A': 7, 'Z': 3} dic2 = {k.lower(): dic.get(k.lower(), 0) + dic.get(k.upper(), 0) for k in dic.keys()} print(dic2) # {'a': 17, 'b': 34, 'z': 3}
3、 集合推导式
# 计算列表中每个值的平方,自带去重功能 squared = {x**2 for x in [1, -1, 2]} print(squared) # {1, 4}
四、生成器表达式
g1 = (i*i for i in range(1, 3)) # 生成器表达式用() 括起来,列表推导式是用[],其他规则与列表推导式一致。 print(g1.__next__()) # 1 print(g1.__next__()) # 4 print(g1.__next__()) # 不会输出值,会报错,__next__方法只取1和2的值,不会取3的值
列表推导式,生成器表达式:
优点: 构造简单,一行完成
缺点: 不能排错,使用debug模式时,无法看到执行步骤
他不能构建复杂的数据结构。
转载于:https://www.cnblogs.com/caoyinshan/p/10116332.html
python (八)迭代器、生成器、列表推导式相关推荐
- python列表推导式生成随机数_python 【迭代器 生成器 列表推导式】
python [迭代器 生成器 列表推导式] 一.迭代器 1.迭代器 如何从列表.字典中取值的 index索引 ,key for循环 凡是可以使用for循环取值的都是可迭代的 可迭代协议 :内部含 ...
- python 三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数
一.三元表达式 语法:[成立1 if condition1 else成立2 if condition2 else ...if 成立N conditionN else 不成立] sex = 'man' ...
- Python 三元表达式、列表推导式、生成器表达式
一.三元表达式 三元表达式,也称为if,else的紧凑形式.具体用法如下: def max(a,b):if a>b:return aelse:return bdef max(a,b):retur ...
- 列表推导式 python原理_Python进阶-列表推导式详解总结
列表推导式并不是什么特别的技术,它只是一种创建列表的简洁方法,目的是为了让大家写程序时更方便更快捷,写出更简洁的代码 初识列表 现在请创建一个list,元素为1到9的整数,先用普通方法做 lst = ...
- Python基础教程:列表推导式对比For循环执行效率
如果把1-10以内的元素追加到一个新的列表表中,如果使用for循环我们可以这么做: a = [] for i in range(1,11):a.append(i) print(a) 输出结果如下: 如 ...
- 列表推导式 python原理_python之列表推导式
1. 定义 用一行构建代码 例题 # 构建一个1-100的列表 l1 = [i for i in range(1,101)] print(l1) # 输出结果 [1,2,3,4,5,6,...100] ...
- Python基础教程:列表推导式详解
我们经常需要这样处理一个列表:把一个列表里面的每个元素, 经过相同的处理 ,生成另一个列表. 比如:一个列表1,里面都是数字,我们需要生成一个新的列表B,依次存放列表A中每个元素的平方 怎么办? 当然 ...
- Python(2.7.6) 列表推导式
列表推导式是利用已有的列表导出新的列表,它的工作方式类似于 for 循环. 例如,有一个列表,现在想得到一个对应的列表,使得每个元素是原有列表中元素的平方: >>> [x ** 2 ...
- python双重for循环 列表推导式_Python 列表推导式
列表推导式(list comprehension)是利用其它列表创建新列表的一种方式.它的工作方式类似于for循环,例如: >>> [x*x for x in range(10)] ...
- python 优雅的 列表推导式(for in if)生成器表达式 集合推导式和字典推导式 列表动态构建器(不用先创建空容器【空列表】,再一个一个append()进去那样麻烦了)
文章目录 用于创建列表也是非常方便的,比如获取当前连接的所有Intel Realsense摄像头序列号 写代码的时候偶然将这段优雅的代码码了出来,感觉很神奇,就去搜索,原来这种语法叫做列表推导式(fo ...
最新文章
- HarmonyOS shape 的使用
- 离散蚁群算法实例(求解旅行商问题)
- 热血致敬!曾影响几代科学巨匠的传奇经典,至今仍无人能超越!
- c++中的继承--3(多继承问题,菱形继承)
- idea设置中文界面_《英雄联盟手游》设置界面中文翻译图分享 外服汉化界面一览...
- awk按分隔符的不同取出不同的列
- python 类方法 函数_Python OOP类中的几种函数或方法总结
- Mybatis SQL片段
- python tkinter库 pack布局方法调用
- 图解设计模式-Chain Of Responsibility模式
- Mono.Cecil使用示例之获取源文件路径
- C++ 几种智能指针的简单实现
- 黑鹰的VIP数据库(一)
- java对接 布防 海康威视_java web整合海康威视录像机摄像SDK
- python作业_python小作业
- pku 2251 Dungeon Master 基本BFS
- 荣耀红米们开启新征途:这届手机品牌为何热衷养“干儿子”?
- 树莓派+Ardunio的魔方机器人
- 【微信开发】---- 公众号支付
- Python矩阵计算类:计算矩阵加和、矩阵乘积、矩阵转置、矩阵行列式值、伴随矩阵和逆矩阵