python函数式编程之迭代器
什么是迭代器
顾名思义,就是更新换代的意思
python中的迭代器就是根据上一个结果生成下一个结果,一直循环往复不断重复的过程
迭代器有两个特点:
- 1.不断重复同一个过程
- 2.根据上一个结果生成下一个结果
迭代器的定义
先来看两个例子
代码一:
while True:
cmd = input("input your command: ").strip()
print(cmd)
代码二:
l1 = ["a", "b", "c", "d"]
count = 0
while count < len(l1):
print(l1[count])
count += 1
在代码一中,让用户不断输入命令,然后打印用户输入的命令,这是一个不断重复的过程,但是后一个结果跟前一个结果没有什么联系,所以代码一不是迭代器
在代码二中,先定义一个列表l1和count,在count的值小于列表l1的长度中,打印列表中count索引的值,然后count的值加1,这几行代码符合迭代器的定义
代码二的执行过程:
首先,打印列表l1中count索引的值,这是一个不断重复的过程
然后,每循环一次,count的值就在以前的基础上增加1,直到count的值等于列表l1的长度时,循环中止
所以代码一不是迭代器,代码二才是符后迭代器的定义标准
迭代器的作用
python中常见的数据类型包括字符串,列表,元组,字典,集合,文件
我们知道,python中的数据类型又分为有序和无序
对于有序数据类型,可以如上面的代码二所示,使用索引遍历有序数据类型中的元素
而对于无序数据类型,就不可以使用索引来遍历其中的元素了,此时可以使用for循环来遍历其中的元素
现在来看看for循环到底做了哪些事,可以取出无序数据类型中的元素
dic1 = {"a": 1, "b": 2, "c": 3, "d": 4, }
for k in dic1:
print(k)
执行上面的程序,可以打印出字典dic1中所有的键
实际上,python为了提供一种不依赖于索引的迭代方式,python会为一些对象内置__iter__
方法
在python中,如果一个对象有__iter__方法,那么这个对象就是可迭代对象
执行obj.__iter__()方法得到的结果就是迭代器
所以python中的迭代器,都会有__iter__方法和__next__方法
以上面定义的dic1为例
dic1 = {"a": 1, "b": 2, "c": 3, "d": 4, }
i = dic1.__iter__() # dic1.__iter__方法执行结果得到一个迭代器i
print(i) # 打印迭代器,得到结果:<dict_keyiterator object at 0x0000000002DBD278>
print(i.__next__()) # 执行迭代器i中的__next__方法,得到dic1中的一个元素,然后打印迭代出的元素
print(i.__next__()) # 再次执行迭代器的__next__方法,得到dic1的第二个元素,然后打印出来
print(i.__next__()) # 第三次执行迭代器的__next__方法,得到dic1的第三个元素,然后打印出来
由于python的字典是无序的数据类型
,所以每次得到的dic1中的元素可能是不相同的
执行三次__next__方法,得到的结果如下
a
b
c
上面dic1的长度为4,如果执行5次__next__方法,会出错什么结果
dic1 = {"a": 1, "b": 2, "c": 3, "d": 4, }
i = dic1.__iter__()
print(i.__next__())
print(i.__next__())
print(i.__next__())
print(i.__next__())
print(i.__next__())
程序执行结果
a
File "D:\python3\lib\unittest\loader.py", line 153, in loadTestsFromName
b
module = __import__(module_name)
c
File "E:\python_learn\py_code\test.py", line 21, in <module>
d
print(i.__next__())
StopIteration
可以看到,python解释器在执行第五次__next__方法时,抛出了StopIteration
的错误,这说明如果执行__next__方法的次数超出迭代器的长度时,python解释会抛出异常
迭代器的优缺点
迭代器的优点
1.提供一种不依赖于索引的取值方式
2.提供惰性计算,每执行一次__next__方法,只会从迭代器中取出一个值,不管这个数据长度有多大,使用迭代器取值时,每取出一个值,占用的内存空间都一个元素的大小,非常节省内存空间
迭代器的缺点
1.取值比较麻烦。如果想用迭代器的方式取出列表中的第三个值,必须调用三次__next__方法,才能取出第三个值,而前两次取出的值实际上是没有作用的
2.一次性的,只能向后迭代,不能回退。如果运行两次__next__方法后,就不可能回退再去了迭代器的第一个值
3.不能获取到迭代器的长度,只能不停执行__next__方法,直到出现StopIteration的提示,此时才能知道迭代器的长度
for循环的执行过程
定义一个列表,使用for循环遍历取出列表中的值
l1 = ['a', 'b', 'c', 'd']
for i in l1:
print(i)
在for循环的执行过程中,实际上for循环是把in后面的对象执行__iter__方法,得到一个迭代器对象
,然后不停执行迭代器对象中的__next__方法,得到元素
,然后把迭代出来的元素赋值给i
,再调用print方法打印元素i,直到for循环捕捉到StopIteration异常
,结束循环,程序停止
类似于下面的代码
l1 = ['a', 'b', 'c', 'd']
obj = l1.__iter__()
while True:
try:
i = obj.__next__()
print(i)
except StopIteration:
break
判断一个对象是迭代器对象还是可迭代对象
只要一个对象有__iter__方法,这个对象就是可迭代对象
一个可迭代对象有__next__方法,这个对象就是迭代器对象
判断python中的字符串,列表,元组,字典和文件对象是否是可迭代对象和迭代器对象
示例代码
from collections import Iterable, Iterator
s1 = "hello"
l1 = ['a', 'b', 'c', 'd']
t1 = ('a', 'b', 'c', 'd')
set1 = {'a', 'b', 'c', 'd'}
dic1 = {"a": 1, "b": 2, "c": 3, "d": 4, }
f1 = open("db.txt", "w", encoding="utf-8")
print(isinstance(s1, Iterable))
print(isinstance(l1, Iterable))
print(isinstance(t1, Iterable))
print(isinstance(set1, Iterable))
print(isinstance(dic1, Iterable))
print(isinstance(f1, Iterable))
print("*" * 30)
print(isinstance(s1, Iterator))
print(isinstance(l1, Iterator))
print(isinstance(t1, Iterator))
print(isinstance(set1, Iterator))
print(isinstance(dic1, Iterator))
print(isinstance(f1, Iterator))
执行结果:
True
True
True
True
True
True
******************************
False
False
False
False
False
True
从上面的例子,可以看出,字符串,列表,元组,集合,字典和文件都是可迭代对象
,其中只有文件是迭代器对象
在上面,我们知道,使用for遍历对象中的值时,是把in后面的对象的变为可迭代对象,然后调用__next__方法取出对象中的元素
既然文件本身就是迭代器对象,那使用for循环获取文件的内容时,又是怎么做的呢
先打开一个文件,打印出这个文件对象,再调用文件对象的__iter__方法得到迭代器对象,判断两个对象是否是同一个对象
f1 = open("db.txt", encoding="utf-8")
print(f1)
obj = f1.__iter__()
print(obj)
print(obj is f1)
执行结果
<_io.TextIOWrapper name='db.txt' mode='r' encoding='utf-8'>
<_io.TextIOWrapper name='db.txt' mode='r' encoding='utf-8'>
True
得到结论:
如果一个对象可以被for循环迭代,则这个对象一定是可迭代对象
文件对象被执行__iter__方法,得到的结果仍然是一个迭代器对象
python函数式编程之迭代器的更多相关文章
- python 函数式编程:高阶函数,map/reduce
python 函数式编程:高阶函数,map/reduce #函数式编程 #函数式编程一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数 #(一)高阶函数 f=abs f print ...
- Python函数式编程:从入门到走火入魔
一行代码显示"爱心" >>> print]+(y*-)**-(x**(y*<= ,)]),-,-)]) Python函数式编程:从入门到走火入魔 # @fi ...
- python函数式编程,列表生成式
1.python 中常见的集中存储数据的结构: 列表 集合 字典 元组 字符串 双队列 堆 其中最常见的就是列表,字典. 2.下面讲一些运用循环获取字典列表的元素 >>> dic={ ...
- (转)Python函数式编程——map()、reduce()
转自:http://www.jianshu.com/p/7fe3408e6048 1.map(func,seq1[,seq2...]) Python 函数式编程中的map()函数是将func作用于se ...
- python 函数式编程学习笔记
函数基础 一个函数就是将一些语句集合在一起的部件,它们能够不止一次地在程序中运行.函数的主要作用: 最大化的代码重用和最小化代码冗余 流程的分解 一般地,函数讲的流程是:告诉你怎样去做某事,而不是让你 ...
- Python函数式编程(进阶2)
转载请标明出处: http://www.cnblogs.com/why168888/p/6411915.html 本文出自:[Edwin博客园] Python函数式编程(进阶2) 1. python把 ...
- Python函数式编程——map()、reduce()
文章来源:http://www.pythoner.com/46.html 提起map和reduce想必大家并不陌生,Google公司2003年提出了一个名为MapReduce的编程模型[1],用于处理 ...
- python函数式编程之返回函数、匿名函数、装饰器、偏函数学习
python函数式编程之返回函数 高阶函数处理可以接受函数作为参数外,还可以把函数作为结果值返回. 函数作为返回值 def laxy_sum(*args): def sum(): ax = 0; fo ...
- Python函数式编程简介
参考原文 廖雪峰Python函数式编程 函数 函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程 ...
随机推荐
- js 判断一个文本框是否获得焦点
1.js 判断一个文本框是否获得焦点 // 可以用document.activeElement判断 // document.activeElement表示当前活动的元素 // 查找你要判断的文本框 ...
- Failed to get D-Bus connection: Operation not permitted解决
docker中安装centos无法使用systemctl命令管理进程,报以下错误: Failed to get D-Bus connection: Operation not permitted 原因 ...
- 理解SSL/TLS协议
理解SSL/TLS协议 背景 早期我们在访问web时使用HTTP协议,该协议在传输数据时使用明文传输,明文传输带来了以下风险: 1.信息窃听风险,第三方可以获取通信内容 2.信息篡改风险,第三方可以篡 ...
- svn一整套使用,从下载到整个服务器搭建完成的详细说明
SVN服务器的本地搭建和使用 Subversion是优秀的版本控制工具,其具体的的优点和详细介绍,这里就不再多说. 首先来下载和搭建SVN服务器. 现在Subversion已经迁移到apache网站上 ...
- 07_Python变量内存地址、小数据池
一.变量在内存中的地址 变量:用来标识(identify)一块内存区域.为了方便表示内存,我们操作变量实质上是在操作变量指向的那块内存单元.编译器负责分配.我们可以使用Python内建函数id()来获 ...
- 结合Nginx以cgi方式安装php5.5.4
新建用户及用户组 groupadd webuser useradd -g webuser webuser 下载php-5.5 下载链接:http://pan.baidu.com/s/1i3CBshv ...
- NOIP2016提高组初赛(C++语言)试题 个人的胡乱分析
最近在做历年的初赛题,那我捡几道比较有代表性的题说一下好了 原题可以在这里看:https://wenku.baidu.com/view/10c0eb7ce53a580217fcfede.html?fr ...
- BZOJ 1025: [SCOI2009]游戏 [置换群 DP]
传送门 题意:求$n$个数组成的排列变为升序有多少种不同的步数 步数就是循环长度的$lcm$..... 那么就是求$n$划分成一些数几种不同的$lcm$咯 然后我太弱了这种$DP$都想不出来.... ...
- 二维码开源库ZBar-吐槽篇
前不久在网上看到一篇文章<QR-Decoder-OV5640 二维码识别> ,是某开发板的教程.记得对应的开发板以前购买过,当初只是为了看OV5640的JPG的输出效果,结果由于公司奇葩的 ...
- laravel中实现短信发送验证码
前段时间想实现一个短信验证码的功能,但是卡了很长时间. 首先我用的是阿里云的短信服务业务,其首次接入流程如下: 在阿里云上开通短信服务后需要做的: 1,申请签名 2,申请模板 3,创建Acces ...