新闻资讯  快讯  焦点  财经  政策  社会
互 联 网   电商  金融  数据  计算  技巧
生活百科  科技  职场  健康  法律  汽车
手机百科  知识  软件  修理  测评  微信
软件技术  应用  系统  图像  视频  经验
硬件技术  知识  技术  测评  选购  维修
网络技术  硬件  软件  设置  安全  技术
程序开发  语言  移动  数据  开源  百科
安全防护  资讯  黑客  木马  病毒  移动
站长技术  搜索  SEO  推广  媒体  移动
财经百科  股票  知识  理财  财务  金融
教育考试  育儿  小学  高考  考研  留学
您当前的位置:首页 > IT > 程序开发 > 语言 > Python

Python 迭代器与生成器

时间:2019-05-15 10:49:08  来源:  作者:

要完全理解透生成器,需要我们先掌握三个概念:

  1. 可迭代对象(Iterable)
  2. 迭代器(Iterator)
  3. 迭代(Iteration)

放一张图来理解,来自这里

<a href=http://www.solves.com.cn/it/cxkf/yy/Python/ target=_blank class=infotextkey>Python</a> 迭代器与生成器

 

额外提到了容器(container),说的是我们的集合类对象,如 list、set、dict,它们将多个元素组织在一起,这些对象就可以称为 container。

可迭代对象:

可直接作用于for循环的对象统称为Iterable 。具体的实现是,Python 中的对象只要定义了__iter__方法(该方法返回一个迭代器对象),或者定义了支持下标索引的__getitem__方法,那么这个对象就是可迭代对象。

>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance([x for x in range(10)], Iterable)
True

迭代器:

可作用于next()函数的对象都是Iterator。具体的实现是,任何对象只要定义了__iter__和__next__方法,那就是迭代器对象;迭代器表示一个惰性计算的序列,需要__iter__返回迭代器自身,__next__返回迭代器中的下一个值,迭代到结尾时引发 StopIteration 异常;也就是说迭代器在遍历集合时,并不是将所有的元素事先都准备好,而是迭代到某个元素时才去计算该元素,利用这一特性我们可以去遍历一些巨大的集合,之前总结的函数式编程中,map,reduce,filter函数返回的就是一个新的迭代器。

还有一点需要明确的,迭代器都是可迭代对象,可迭代对象可以通过iter()返回一个新的迭代器。

>>> L = [1, 2, 3, 4, 5]
>>> '__iter__' in dir(L)
True
>>> '__next__' in dir(L)
False
>>> newL = iter(L)
>>> '__next__' in dir(newL)
True
>>> newL.__next__()
1
>>> newL.__next__()
2
# 定义斐波拉契数的迭代器
>>> class fib(object):
... def __init__(self):
... self.prev = 0
... self.curr = 1
... def __iter__(self):
... return self
... def __next__(self):
... value = self.curr
... self.curr += self.prev
... self.prev = value
... return value
... 
>>> f = fib()
>>> for i in f:
... if i > 20: break
... print(i)
... 
1
1
2
3
5
8
13

从上面的迭代操作中,可以看出 for 循环其实是调用__iter__获得迭代器,再调用__next__获取元素,迭代器内部状态保存在当前实例对象的prev以及cur属性中,在下一次调用中将使用这两个属性。每次调用next()方法都会执行以下两步操作:

  1. 修改状态,以便下次调用next()方法
  2. 计算当前调用的结果

迭代器的使用非常普通,Python的内置库itertools就是专门返回迭代器对象的,这篇博文专门介绍itertools库的,我从中列举了一些:

# 累加
>>> import itertools
>>> a = itertools.accumulate(range(10))
>>> a
<itertools.accumulate object at 0x7fb030907388>
>>> print(list(a))
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
# 连接列表或迭代器
>>> c = itertools.chain(range(3), range(4), [0, 1, 2, 3, 4])
>>> print(list(c))
[0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4]
# 按照真值表筛选元素
>>> x = itertools.compress(range(5), (True, False, True, True, False))
>>> print(list(x))
[0, 2, 3]
# 计数器,可以指定起始位置和步长
>>> x = itertools.count(start=20, step=-1)
>>> print(list(itertools.islice(x, 0, 10, 1)))
[20, 19, 18, 17, 16, 15, 14, 13, 12, 11]
# 按照分组函数的值对元素进行分组
>>> x = itertools.groupby(range(10), lambda x: x < 5 or x > 8)
>>> for condition, numbers in x: 
... print(condition, list(numbers))
True [0, 1, 2, 3, 4] 
False [5, 6, 7, 8] 
True [9]
# 类似map
>>> x = itertools.starmap(str.islower, 'aBCDefGhI')
>>> print(list(x))
[True, False, False, False, True, True, False, True, False]

生成器:

有了前面的铺垫,我们就能更好地理解生成器了。生成器是什么?说白了生成器就是一种特殊的迭代器,不过它的实现方式更为简单优雅,同样我们可以明确的是,任何生成器都是迭代器,生成器也是一个惰性计算的序列。

我们来看看生成器的两种定义方式:

1、生成器表达式:

>>> [i * i for i in range(5)]	# 注意 Python3 中 range函数是迭代器
[0, 1, 4, 9, 16]
# 根据列表生成式,只需要简单修改就可以定义生成器
>>> (i * i for i in range(3))
<generator object <genexpr> at 0x7f59ed8fc3b8>

2、另一种定义复杂推导算法的生成器需要引入一个强大的关键字yield:

# 斐波那契序列的生成器函数
>>> def fib():
... prev = curr = 1
... yield prev #1
... yield curr #2
... while True:
... prev, curr = curr, prev + curr
... yield curr
... 
>>> f = fib()
>>> f
<generator object fib at 0x7f85cca9d410>
>>> for i in f:	 # 还可以使用 next() 遍历生成器
... if i > 20: break
... print(i)
... 
1
1
2
3
5
8
13

分析一下流程:

  1. 调用生成器函数时只返回一个 generator 对象 f,函数并没有执行;
  2. 通过 for 循环生成器才开始执行,执行到 #1 yield prev 处,返回 yield 处的参数 prev,此时就打印出了1;
  3. 继续 for 循环,生成器函数将在上一次停止的语句处继续执行,遇到 #2 yield curr 返回,此时又打印出了1;
  4. 如此反复,直到i大于20跳出循环结束调用。

对比迭代器和生成器,实现同样的功能,生成器会显得更加优雅简洁。

迭代

一句话总结迭代:按照一定的顺序逐个访问容器中每一个元素的过程;也就是我们折腾斐波那契序列的过程

限于篇幅,生成器就介绍到这里,但生成器的威力远不止此,下一篇将通过生成器和 yield 引出协程和异步IO等。
 



Tags:Python   点击:()  评论:()
声明:本站部分内容来自互联网,如有任何版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▌相关评论
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
▌相关推荐
作者 | Serdar Yegulalp译者 | 姜松浩,责编 | 屠敏转载自 CSDN(ID:CSDNnews)Python因其强大、灵活且易于使用等特性,而赢得了声誉。这些优点使其在各种各样的应用程序、工作流程...【详细内容】
2019-07-19   Python  点击:(3)  评论:(0)  加入收藏
本文要点 字符串拼接 拆分含有多种分隔符的字符串 判读字符串a是否以字符串b开头或结尾 调整字符串中文本的格式 对字符串进行左,右,居中对齐 删除字符串中不需要的字符字符串...【详细内容】
2019-07-19   Python  点击:(1)  评论:(0)  加入收藏
导读:Python数据工具箱涵盖从数据源到数据可视化的完整流程中涉及到的常用库、函数和外部工具。其中既有Python内置函数和标准库,又有第三方库和工具。这些库可用于文件读写、...【详细内容】
2019-07-18   Python  点击:(3)  评论:(0)  加入收藏
前置内容为了更容易理解闭包,在说闭包之前,讲一下两个概念:作用域和嵌套函数。 作用域作用域是变量能被访问的范围,定义在函数内的变量是局部变量,局部变量的作用范围只能在函数...【详细内容】
2019-07-17   Python  点击:(1)  评论:(0)  加入收藏
引言:年初参与到一个后台系统开发的项目中,里面涉及了很多接口,我做为项目组测试人员,需要对这些接口进行测试,一开始使用 postman 工具测试,很是方便。但随着接口数量的增加,不光...【详细内容】
2019-07-17   Python  点击:(5)  评论:(0)  加入收藏
48作者 | Python语音识别来源 | 深度学习与python(ID:PythonDC)不管是机器学习、web开发或者爬虫,数据库都是绕不过去的。那么今天我们就来介绍Python如何Mysql数据库进行连...【详细内容】
2019-07-17   Python  点击:(0)  评论:(0)  加入收藏
使用 pyenv 和 virtualwrapper 来管理你的虚拟环境,可以避免很多困惑。-- Matthew Broberg(作者)作为 Python 开发者和 MacOS 用户,拿到新机器首先要做的就是设置 Python 开发...【详细内容】
2019-07-12   Python  点击:(6)  评论:(0)  加入收藏
搜索是大数据领域里常见的需求。Splunk和ELK分别是该领域在非开源和开源领域里的领导者。本文利用很少的Python代码实现了一个基本的数据搜索功能,试图让大家理解大数据搜索...【详细内容】
2019-07-12   Python  点击:(6)  评论:(0)  加入收藏
前言我们所说的加密方式,都是对二进制编码的格式进行加密的,对应到Python中,则是我们的Bytes。将字符串和Bytes互相转换可以使用encode()和decode()方法。 URL编码正常的URL中...【详细内容】
2019-07-12   Python  点击:(6)  评论:(0)  加入收藏
IP合法性校验是开发中非常常用的,看起来很简单的判断,作用确很大,写起来比较容易出错,今天我们来总结一下,看一下3种常用的IP地址合法性校验的方法。IPv4的ip地址格式:(1~255).(0~255...【详细内容】
2019-07-04   Python  点击:(10)  评论:(0)  加入收藏
经常写爬虫的都知道,有些页面在登录之前是被禁止抓取的,比如知乎的话题页面就要求用户登录才能访问,而 “登录” 离不开 HTTP 中的 Cookie 技术。登录原理Cookie 的原理非常简...【详细内容】
2019-07-02   Python  点击:(20)  评论:(0)  加入收藏
image.png技巧 #1字符串翻转a = "codementor">>> print "Reverse is",a[::-1]翻转后的结果为 rotnemedoc技巧 #2矩阵转置mat = [[1, 2, 3], [4, 5, 6]]>>> zip(*mat)[(1, 4)...【详细内容】
2019-07-01   Python  点击:(12)  评论:(0)  加入收藏
1.安装引入模块 安装mysql模块,在windows和ubuntu中 windows里安装mysql模块 Linux里安装mysql模块 在文件中引入模块import pymysql 2.Connection对象 用于建立与数据库的...【详细内容】
2019-06-28   Python  点击:(14)  评论:(0)  加入收藏
常遇到两类朋友。一类是会爬虫但不知道如何进一步做数据分析的,一类是平常用 Excel 做分析但不太会用 Python 分析的。如果和你很像,那下面这篇系统长文会很适合你,建议先收藏...【详细内容】
2019-06-26   Python  点击:(14)  评论:(0)  加入收藏
文 | 我爱学Python@简书 编辑 | EarlGrey推荐 | 编程派公众号(ID:codingpy)昨天在上厕所的时候突发奇想,当你把usb插进去的时候,能不能自动执行usb上的程序。查了一下,发现只有win...【详细内容】
2019-06-25   Python  点击:(12)  评论:(0)  加入收藏
迭代器是一个更抽象的概念,任何对象,如果它的类有 next 方法和 iter 方法返回自己本身,对于 string、list、dict、tuple 等这类容器对象,使用 for 循环遍历是很方便的。在后台 f...【详细内容】
2019-06-24   Python  点击:(8)  评论:(0)  加入收藏
python强大的引进-生成器。这就是我们今天要学习的这一章内容。定义:在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。换句更简单的话来理解:任何包含yield语句的...【详细内容】
2019-06-21   Python  点击:(14)  评论:(0)  加入收藏
很多同学在使用python进行自动化测试的时候,会涉及到数据库数据校验的问题,因为不知道如何在python中如何对接数据库,这个时候会一脸茫然。今天在这里给大家汇总一下python对接...【详细内容】
2019-06-20   Python  点击:(24)  评论:(0)  加入收藏
对正常的网络行为建立模型,要处理的网络数据和保存在模型内的正常模式相匹配,如果不在正常范围内,就认为是攻击行为,对其做出处理。网络安全攻击与防御的工具有哪些? 网络安全与...【详细内容】
2019-06-20   Python  点击:(19)  评论:(0)  加入收藏
业务场景:用户下单之后,在规定时间内如果不完成付款,订单自动取消,并且释放库存使用技术:Redis键空间通知(过期回调)用户下单之后将订单id作为key,任意值作为值存入redis中,给这条数...【详细内容】
2019-06-20   Python  点击:(37)  评论:(0)  加入收藏
推荐资讯
相关文章
栏目更新
栏目热门