新闻资讯  快讯  焦点  财经  政策  社会
互 联 网   电商  金融  数据  计算  技巧
生活百科  科技  职场  健康  法律  汽车
手机百科  知识  软件  修理  测评  微信
软件技术  应用  系统  图像  视频  经验
硬件技术  知识  技术  测评  选购  维修
网络技术  硬件  软件  设置  安全  技术
程序开发  语言  移动  数据  开源  百科
安全防护  资讯  黑客  木马  病毒  移动
站长技术  搜索  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   点击:()  评论:()
声明:本站部分内容来自互联网,内容观点仅代表作者本人,如有任何版权侵犯请与我们联系,我们将立即删除。
▌相关评论
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
▌相关推荐
《九章算术》,一本成书于东汉初期、汇总了中国先秦至汉代数学成就的著作。Python版本的《九章算术》,以编程的方式诠释《九章》,通过《九章》学习编程。简练精致的文言、清晰明...【详细内容】
2020-03-17   Python  点击:(6)  评论:(0)  加入收藏
一、函数、输入、评估、输出函数 1、函数函数定义:根据输入的参数产生不同输出结果的功能过程。使用方式:<函数名>(<参数>)函数效果:类似数学中的函数,y=f(x) 2、三个简单函数 (1...【详细内容】
2020-03-16   Python  点击:(6)  评论:(0)  加入收藏
pytest介绍pytest是一款强大的python测试工具,可以胜任各种级别的软件测试工作,可以自动查找测试用并执行,并且有丰富的基础库,可以大幅度提高用户编写测试用例的效率,具备可扩...【详细内容】
2020-03-16   Python  点击:(8)  评论:(0)  加入收藏
今天给大家介绍个有意思的工具,不知道你有没有听说过中间人攻击(Man-in-the-middle attack)简称 MITM,是一种“间接”的入侵攻击,这种攻击模式是通过各种技术手段将受入侵者控制...【详细内容】
2020-03-15   Python  点击:(3)  评论:(0)  加入收藏
开发安全、高质量代码的 5 款顶级 Python 工具原创 InfoQ 2020-03-12 16:12:50 为提高代码的质量、安全性和可维护性,软件工程师每天会用到无数工具。我会列出一些自己最喜...【详细内容】
2020-03-15   Python  点击:(8)  评论:(0)  加入收藏
本文介绍如何利用python来对MySQL数据库进行操作,本文将主要从以下几个方面展开介绍:1.数据库介绍2.MySQL数据库安装和设置3.Python操作MySQL在Python3.X上安装MySQL驱动创建...【详细内容】
2020-03-15   Python  点击:(11)  评论:(0)  加入收藏
程序员编程分享 2020-02-24 15:06:26 当我开始学习Python的时候,有些事我希望我一早就知道。我花费了很多时间才学会这些东西。我想要把这些重点都编纂到一篇文章当中。这篇...【详细内容】
2020-03-15   Python  点击:(8)  评论:(0)  加入收藏
Web 项目设计内容聚合器(Content Aggregator)1. 技术细节该项目设计的主要目标是聚合内容。首先,我们需要知道内容聚合器从哪些站点获取内容。然后,使用请求库来发送 HTTP 请...【详细内容】
2020-03-15   Python  点击:(12)  评论:(0)  加入收藏
不管学习哪门语言都希望能做出实际的东西来,这个实际的东西当然就是项目啦,不用多说大家都知道学编程语言一定要做项目才行。这里整理了70个Python实战项目列表,都有完整且详细...【详细内容】
2020-03-15   Python  点击:(36)  评论:(0)  加入收藏
0基础小白怎么学Python?今天给大家分享一些学习Python的基本概念图,入门书籍、视频教程以及学习路上最有效的方法。Python基本概念最全图1.Python 解释器: 2.Python数据结构...【详细内容】
2020-03-15   Python  点击:(7)  评论:(0)  加入收藏
鉴于大多数书籍在编写上都结构混乱,无法体现出知识的系统性、逻辑性和层次性。特整理出学Python最基础的知识学习框架,希望帮助大家快速入门。要快速学会Python,谨记&lsquo;3个...【详细内容】
2020-03-15   Python  点击:(8)  评论:(0)  加入收藏
我是个只会用Excel的数据分析工作者。有一天,我和朋友约好晚上一起吃饭,离下班还有5分钟,老板突然Q我:老板:你今天加个班我:好呀好呀老板:我有几个Excel,需要你把它们合成一张表我:...【详细内容】
2020-03-14   Python  点击:(8)  评论:(0)  加入收藏
网络相关 通用 urllib &ndash; 网络库(标准库) requests &ndash; 网络库 grab &ndash; 网络库(基于pycurl) pycurl &ndash; 网络库 (与 libcurl 绑定) urllib3 &ndash; 具有...【详细内容】
2020-03-14   Python  点击:(14)  评论:(0)  加入收藏
auto-py-to-exe是一个简单小工具,用一个简单的小界面图形化的方式将.py转换成exe,该界面使用Python中的Eel和PyInstaller构建,这是一个开源小项目,你可以在Github上查看它,Github...【详细内容】
2020-03-13   Python  点击:(8)  评论:(0)  加入收藏
pyenv 多版本管理工具1.linux安装pyenv方式git 安装1、安装git# yum install git -y2、安装Python编译依赖# yum -y install gcc make patch gdbm-devel openssl-devel s...【详细内容】
2020-03-13   Python  点击:(4)  评论:(0)  加入收藏
/1 前言/细心的小伙伴可能知道,小编之前发布过一篇使用Python发现酒店隐藏的针孔摄像头,没有来得及上车的小伙伴也没关系,可以戳这篇文章了解一下:使用Pyhton带你分析酒店里的针...【详细内容】
2020-03-09   Python  点击:(6)  评论:(0)  加入收藏
用 Python 关机你肯定听过或者实践过,那么用 Python 开机呢?这是一个神奇的方法,教你如何用 Python 来开机。本文目标 远程开机原理 Python 远程开机代码实现 Python 关机说明P...【详细内容】
2020-03-08   Python  点击:(7)  评论:(0)  加入收藏
首先,打开电脑终端并执行以下命令安装Homebrew:/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"更多关于Homebrew,...【详细内容】
2020-03-08   Python  点击:(8)  评论:(0)  加入收藏
作者:HelloGitHub-Prodesire一、前言在本系列前面所有文章中,我们分别介绍了 argparse、docopt 和 click 的主要功能和用法。它们各具特色,都能出色地完成命令行任务。argpars...【详细内容】
2020-03-08   Python  点击:(6)  评论:(0)  加入收藏
现如今面向对象编程的使用非常广泛,本文我们就来探讨一下Python中的面向对象编程。作者 | Radek Fabisiak译者 | 弯月,责编 | 郭芮出品 | CSDN(ID:CSDNnews)以下为译文:Python支持...【详细内容】
2020-03-05   Python  点击:(12)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条