Python基础手册19——迭代器

一、迭代器

我们知道 for 循环可以用于 Python 中的任何序列类型,实际上 for 循环可用于Python 中的任何可迭代类型。对于 Python 中所有会从左至右扫描对象的迭代工具而言都是如此,这些迭代工具包括了 for 循环、列表解析、in 成员关系测试以及 map() 内置函数等,他们都支持任何的可迭代类型。

”可迭代对象“ 的概念在 Python 中基本上和序列概念是一样的:如果对象是实际保存的序列,或者可以在迭代工具环境中(例如,for循环)一次产生一个结果的对象,就看做这个对象是可迭代的。总之,可迭代对象包括实际序列和按照需求而计算的虚拟序列(比如:range对象 和 生成器函数)。


1、迭代协议: next()

文件对象有一个方法 __next__() ,每次调用时,就会返回文件的下一行,到达文件末尾时, __next__() 会引发内置的 StopInteration 异常。

这个接口就是Python中的迭代协议:有一个 __next__() 方法的对象在迭代工具的依次迭代中会依次的前进到下一个结果,而在一系列结果的末尾时,则会引发StopInteration 异常。在Python中,任何这类对象都认为是可迭代的。任何这类对象也能以 for 循环或其他迭代工具遍历,因为所有的迭代工具内部工作起来都是在每次迭代中调用可迭代对象的 __next__() 方法,并且捕捉 StopInteration 异常来确定何时离开。

所以逐行读取文本文件的最佳方法就是根本不要去读取,而是让 for 循环在每次迭代中自动调用文件对象的 __next__() 方法从而前进到下一行。

这里的 print() 使用 end='' 参数来抑制自动添加一个 '\n',因为字符串已经有一个(如果 print() 再自动加上一个,我们的输出将会多输出一个空行)。

上面是读取文本文件的最佳方式,因为这是代码最简单、运行最快的方法,并且从内存使用情况来说也是最好的。迭代器在 Python 中是以 C 语言的速度运行的,而 while 循环则是通过 Python 虚拟机运行 Python 字节码的。所以我们一直建议在能够使用 for 循环的时候都使用 for 循环,因为他使用更方便,运行更高效。


2、内置函数:next() 和 iter()

为了更方便的手动迭代可迭代对象,Python 3.0 还提供了一个内置函数 next() ,它会自动调用一个对象的 __next__() 方法。也就是说对于一个可迭代对象,使用 next() 内建函数调用和调用其 __next__() 方法是一样的,但是前者要简单很多。

当 for 循环开始时,会将对象传给 iter() 内置函数,以便从可迭代对象中获得一个迭代器,返回的对象含有需要的 __next__() 方法。

对于文件对象来说是不需要调用 iter() 函数的,因为文件对象拥有自己的迭代器。也就是说,文件对象有自己的 __next__() 方法。

列表以及很多其他的内置对象,自身没有 __next__() 方法,也就是没有自身的迭代器,但是它们支持多次打开(创建)迭代器。对于这样的对象,我们必须调用 iter() 函数来为他们创建迭代器,启动迭代。

尽管Python的迭代工具自动调用这些函数,我们也可以使用它们来手动地应用迭代协议。


3、其他迭代环境

在 Python 的内置工具集中从左至右扫描一个对象的每项工具都定义为在对象上使用了迭代协议。列表解析、in 成员关系测试、map() 内置函数以及像 sorted() 和 zip() 调用这样的内置函数也都使用了迭代协议,所有这些都接收一个可迭代的对象。

Python还包含了各种处理迭代的其他内置函数:

  • sorted() 排序,可迭代对象中的各项;
  • zip() 组合,可迭代对象中的各项;
  • enumerate() 根据相对位置来配对,可迭代对象中的各项,
  • filter() 选择一个函数为真的项;
  • reduce() 针对可迭代对象中的成对的项运行一个函数。


二、Python 3.0 中的可迭代对象

Python 3.0 中的一个基本改变是,它更强调迭代。除了与文件和序列这样的内置类型相关的迭代,字典本身,以及字典的方法 keys(),values() 和 items() 都在 Python 3.0 中返回可迭代对象,就像内置函数 range()、map()、zip() 和 filter() 所做的那样。


1、字典

在Python3.0 中,字典对象也支持创建自己的迭代器,在迭代环境中,会自动一次返回一个键。

字典的 keys() 、values() 和 items() 方法返回可迭代的视图对象,没有自己的迭代器,它们一次产生一个结果项,而不是在内存中一次产生全部结果列表。

注意: 在 Python 3.0 中字典对象是可迭代的(没有自己的迭代器),它返回连续的键。因此无需直接在此环境中调用 keys() 方法,而且这样由于中间生成了dict_keys对象,还会导致执行效率的下降。


2、range() 内置函数

它返回一个可迭代的 range 类型对象,range 对象根据需要产生范围中的数字,而不是在内存中构建一个结果列表。

在 Python 3.0 中 range 对象只支持迭代、索引以及 len() 函数。他不支持任何其他的序列操作。


3、map()、zip() 和 filter() 内置函数

和 range() 类似,map()、zip() 和 filter() 内置函数在 Python 3.0 中也返回可迭代对象以节约内存空间,而不在内存中一次性生成一个结果列表。

和 range() 不同,它们都拥有自己的迭代器——在遍历其结果一次以后,它们就用尽了。换句话说,不能在它们的结果上拥有那些在结果中保持不同位置的多个迭代器。


4、多个迭代器 VS 单个迭代器

range 对象没有自己的迭代器(手动迭代时,我们使用 iter() ,为 range 对象生成一个迭代器),并且它支持在其结果上创建多个迭代器,这些迭代器会记住它们各自的位置。

相反 zip 对象、map 对象 和 filter 对象拥有自己的迭代器(可以直接调用next() 函数进行迭代,不用手动调用 iter() 函数来再次生成迭代器),不支持相同结果上的多个活跃迭代器。


《Python基础手册》系列:

Python基础手册 1 —— Python语言介绍
Python基础手册 2 —— Python 环境搭建(Linux)
Python基础手册 3 —— Python解释器
Python基础手册 4 —— 文本结构
Python基础手册 5 —— 标识符和关键字
Python基础手册 6 —— 操作符
Python基础手册 7 —— 内建函数
Python基础手册 8 —— Python对象
Python基础手册 9 —— 数字类型
Python基础手册10 —— 序列(字符串)
Python基础手册11 —— 序列(元组&列表)
Python基础手册12 —— 序列(类型操作)
Python基础手册13 —— 映射(字典)
Python基础手册14 —— 集合
Python基础手册15 —— 解析
Python基础手册16 —— 文件
Python基础手册17 —— 简单语句
Python基础手册18 —— 复合语句(流程控制语句)
Python基础手册19 —— 迭代器
Python基础手册20 —— 生成器
Python基础手册21 —— 函数的定义
Python基础手册22 —— 函数的参数
Python基础手册23 —— 函数的调用
Python基础手册24 —— 函数中变量的作用域
Python基础手册25 —— 装饰器
Python基础手册26 —— 错误 & 异常
Python基础手册27 —— 模块
Python基础手册28 —— 模块的高级概念
Python基础手册29 —— 包

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • 本文翻译自Functional Programming Howto 本文将介绍Python中函数式编程的特性。在对...
    大蟒传奇阅读 2,596评论 4 14
  • Python 面向对象Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对...
    顺毛阅读 4,205评论 4 16
  • “我不知道真挚中含有多少做作,高尚中蕴藏着多少卑鄙,或者,即使在邪恶里也找得到美德” 明天科三 晚安
    栗子树上的狗咩阅读 257评论 0 0
  • 我不喜欢主人公克服弱点,守护家人并拯救世界这样的情节,更想描述没有英雄、只有平凡人生活的、有点肮脏的世界忽然变得美...
    木卯丁阅读 245评论 0 0
  • 只有TFBOYS能刮开此图层。 刮开图层见十分动人的情书。 ■■■■■■■■■■■■■■■■■■■■■
    添福呀滚滚阅读 235评论 0 0