python的迭代器、生成器、三元运算、列表解析、生成器表达式
一 迭代的概念
迭代是Python最强大的功能之一,是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。
迭代器协议:
- 迭代器协议是指:对象必须提供一个next()方法,执行该方法要么返回带代中的下一项,要么引起一个Stoplteration异常,以终止迭代(只能往后走,不能往前退);
- 可迭代对象:实现了迭代器协议的对象(如何实现:对内部定义一个__iter__方法);
- 协议是一种约定:可迭代对象实现了迭代器协议,python的内部工具(如:for循环,sum,min,max函数等)使用迭代器协议访问对象;
字符串,列表或元组对象都可用于创建迭代器:
#迭代器即迭代的工具,那什么是迭代呢?
#迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值
while True: #只是单纯地重复,因而不是迭代
print('===>') l=[1,2,3]
count=0
while count < len(l): #迭代
print(l[count])
count+=1
二 为何要有迭代器?什么是可迭代对象?什么是迭代器对象?
#1、为何要有迭代器?
对于序列类型:字符串、列表、元组,我们可以使用索引的方式迭代取出其包含的元素。但对于字典、集合、文件等类型是没有索引的,若还想取出其内部包含的元素,则必须找出一种不依赖于索引的迭代方式,这就是迭代器 #2、什么是可迭代对象?
可迭代对象指的是内置有__iter__方法的对象,即obj.__iter__,如下
'hello'.__iter__
(1,2,3).__iter__
[1,2,3].__iter__
{'a':1}.__iter__
{'a','b'}.__iter__
open('a.txt').__iter__ #3、什么是迭代器对象?
可迭代对象执行obj.__iter__()得到的结果就是迭代器对象
而迭代器对象指的是即内置有__iter__又内置有__next__方法的对象 文件类型是迭代器对象
open('a.txt').__iter__()
open('a.txt').__next__() #4、注意:
迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象
三 迭代器对象的使用
dic={'a':1,'b':2,'c':3}
iter_dic=dic.__iter__() #得到迭代器对象,迭代器对象即有__iter__又有__next__,但是:迭代器.__iter__()得到的仍然是迭代器本身
iter_dic.__iter__() is iter_dic #True print(iter_dic.__next__()) #等同于next(iter_dic)
print(iter_dic.__next__()) #等同于next(iter_dic)
print(iter_dic.__next__()) #等同于next(iter_dic)
# print(iter_dic.__next__()) #抛出异常StopIteration,或者说结束标志 #有了迭代器,我们就可以不依赖索引迭代取值了
iter_dic=dic.__iter__()
while 1:
try:
k=next(iter_dic)
print(dic[k])
except StopIteration:
break #这么写太丑陋了,需要我们自己捕捉异常,控制next,python这么牛逼,能不能帮我解决呢?能,请看for循环
四 for循环
#基于for循环,我们可以完全不再依赖索引去取值了
dic={'a':1,'b':2,'c':3}
for k in dic:
print(dic[k]) #for循环的工作原理
#1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
#2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
#3: 重复过程2,直到捕捉到异常StopIteration,结束循环
五 迭代器的优缺点
#优点:
- 提供一种统一的、不依赖于索引的迭代方式
- 惰性计算,节省内存
#缺点:
- 无法获取长度(只有在next完毕才知道到底有几个值)
- 一次性的,只能往后走,不能往前退
说明:
for循环可用于任何可迭代对象
for循环开始时,会通过迭代协议传输给iter()内置函数,从而能够从迭代对象中获得一个迭代器,返回的对象含有需要的next()方法。
六 生成器,生成器表达式和列表解析
什么是生成器?
- 可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他数据类型需要调用自己内置的__iter__方法),所以生成器就是可迭代对象;
生成器分类及在python中的表现形式:(python中有两种不同的方式提供生成器)
- 生成器函数:常规函数定义,但是使用yield语句而不是使用retum语句返回结果,yield语句一次返回一个结果,在每个结果中间挂机函数的状态,以便下次从他离开的地方执行;
- 生成器表达式:类似于列表推导,但是生成器返回按需要产生结果的一个对象,而不是一次构建一个列表;
#生成器函数(只要函数内部包含有yield关键字,那么函数名()的到的结果就是生成器,并且不会执行函数内部代码)
cp = [1,2,3,4,5]
def test():
yield 1
yield 2
yield 3
date = test()
print(next(date))
print(next(date))
print(next(date))
生成器表达式:
#三元表达式
name = "lw"
res = "sb" if name == "lw" else "帅哥"
print(res) egg1 = ["鸡蛋 %s" %i for i in range(10) if i > 5 ]
print(egg1) #正常列表(在内存中存储)
egg_list = []
for i in range(10):
egg_list.append("鸡蛋 %s" %i)
print(egg_list) #列表解析(在内存中存储)
egg = ["鸡蛋 %s" %i for i in range(10)]
print(egg) #生成器表达式(基于迭代器协议转换成可迭代对象,不占内存)
laomuji = ("鸡蛋 %s" %i for i in range(10))
print(laomuji) #<generator object <genexpr> at 0x000001A6F46231A8>
print(laomuji.__next__()) #等于next(laomuji)
生成器的优点
- python使用生成器对延迟操作提供了支持,所谓延迟操作,是指在需要的时候产生结果,而不是立即产生结果,这就是生成器的主要好处;
生成器小结
- 是可迭代对象;
- 实现了延迟计算,省内存;
- 生成器本质和其他数据类型一样,都实现了迭代协议,只不过生成器附加了一个延迟计算省内存的好处,其余的可迭代对象没有这点好处;
#三元表达式
name = "lw"
res = "sb" if name == "lw" else "帅哥"
print(res)
总结:
- 把列表解析的[]换成()得到的就是生成器表达式;
- 列表解析与生成器表达式都是一种便利的变成方式,只不过生成器表达式更省内存;
- python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数也是使用迭代器协议访问对象的,例如:sum函数是python的内置函数,该函数使用迭代器内部协议访问对象,而生成器实现了迭代器协议,所以我们可以直接这样计算一系列值得和;
print(sum(i ** 2 for i in range(3)))
- 而不用多此一举的构建一个列表
print(sum([i ** 2 for i in range(3)]))
python的迭代器、生成器、三元运算、列表解析、生成器表达式的更多相关文章
- python迭代器 生成器 三元运算 列表解析
1.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外,迭代器的一大优 ...
- day13 生成器 三元运算 列表解析
本质上来说生成器迭代器都是一种数据类型,如果你直接打印生成器是无法得出值的,会得到一串内存地址,即一个对象想要得到生成器的值必须要用for或者next,list等来获取 生成器生成器就是一个可迭代对象 ...
- python 10 迭代器和三元运算符
一.迭代器 1.迭代器协议:对象必须提供一种next方法,执行该方法要么返回迭代中的下一项,要么引起一个stopIteration异常,终止迭代 2.可迭代对象:实现了迭代器协议的对象 3.pytho ...
- 搞清楚 Python 的迭代器、可迭代对象、生成器
很多伙伴对 Python 的迭代器.可迭代对象.生成器这几个概念有点搞不清楚,我来说说我的理解,希望对需要的朋友有所帮助. 1 迭代器协议 迭代器协议是核心,搞懂了这个,上面的几个概念也就很好理解了. ...
- Python之Lambda与三元运算
Python之Lambda与三元运算 Lambda 运算 概念:是指一类无需定义标识符(函数名)的函数或者子程序.特点:匿名函数不使用def定义函数,使用lambda来创建匿名函数1.lambda只是 ...
- Python day14迭代器,三元表达式,列表解析以及生成器表达式
1.迭代器 str=['sds','ccc','dw'] lit_1=str.__iter__()#获取迭代器 print(lit_1.__next__())#打印下一个值 # 用while做for的 ...
- Python学习笔记(迭代,列表解析,生成器)
迭代(iterable):支持每次返回自己所包含一个对象的 iter()得到迭代器,.next()遍历列表. 列表解析:根据已有列表高效生成列表的方式. 生成器(Generator): 通过列表生成式 ...
- python 匿名函数与三元运算
匿名函数 匿名函数就是不需要显示式的指定函数名 首先看一行代码: def calc(x,y): return x*y print(calc(2,3)) # 换成匿名函数 calc = lambda x ...
- python基础-3 集合 三元运算 深浅拷贝 函数 Python作用域
上节课总结 1 运算符 in 字符串 判断 : “hello” in "asdasfhelloasdfsadf" 列表元素判断:"li" in ['li', ...
- python匿名函数与三元运算
匿名函数 匿名函数就是不需要显示式的指定函数名 首先看一行代码: def calc(x,y): return x*y print(calc(2,3)) # 换成匿名函数 calc = lambda ...
随机推荐
- python3发送邮件
import smtplib from email.mime.text import MIMEText from email.utils import formataddr import psutil ...
- mysql 与 memcache 字段名后面有空格时会产生什么问题(转)
同事下午遇到一问题,MySQL 和 Memcached 对于同一个key,不能对应起来.最终原因是:PHP将key写入MySQL数据库之前,没有经过trim()过滤首尾空格(关键是尾部空格),结果: ...
- maven 依赖的传递性
1.如图我们有三个项目,项目Age,项目Bge,项目Cge 2.我们使Age项目依赖到Bge项目,Bge项目依赖到Cge项目 Age项目和Bge项目分别执行命令:mvn install 打包*.ja ...
- 《代码敲不队》第八次团队作业:Alpha冲刺 第三天
项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 团队名称 代码敲不队 作业学习目标 掌握软件编码实现的工程要求. 团队项目github仓库地址链接 GitH ...
- java中继承关系学习小结
继承:把多个类中同样的内容提取出来.定义到一个类中,其它类仅仅须要继承该类.就能够使用该类公开的属性和公开的方法. 继承的优点:提高代码的复用性.提高代码的可维护性.让类与类之间产生关系,是多态存 ...
- Windows平台编译openssl-0.9.8k库(32位、64位)
近期工作中使用到了openssl的win64位资料,所以进行前期调研,汇总结果例如以下: [注意]openssl代码所在文件夹中不要带中文,否则"nmake -f ms\ntdll.mak ...
- [Spring实战系列](17)编写切点与声明切面
切点用于准确定位应该在什么地方应用切面的通知. 切点和通知是切面的最基本元素. 在Spring AOP中,须要使用AspectJ的切点表达式语言来定义切点. 关于Spring AOP的AspectJ切 ...
- apple Swift语言新手教程
Apple Swift编程语言新手教程 文件夹 1 简单介绍 2 Swift入门 3 简单值 4 控制流 5 函数与闭包 6 对象与类 7 枚举与结构 1 ...
- Error: CompareBaseObjectsInternal can only be called from the main thread
Posted: 01:39 PM 06-17-2013 hi, we're working on a project where we need to do some calculations on ...
- hdu5592/BestCoder Round #65 树状数组寻找第K大
ZYB's Premutation Memory Limit: 131072/131072 K (Java/Others) 问题描述 ZYBZYB有一个排列PP,但他只记得PP中每个前缀区间的逆 ...