python学习笔记26-语句语法-迭代器和解析

列表解析是对迭代中的项应用一个表达式的for循环的一种近似形式

迭代器--初探:

实际上,for循环甚至比这更为通用:可用于任何可迭代的对象。实际上,对Python中所有会从左至右扫描对象的迭代工具而言都是如此,这些迭代工具包括了for循环、列表解析、in成员关系测试以及map内置函数等。

“可迭代对象”的概念是在Python中是相当新颖的,但它在语言的设计中很普遍。基本上,这就是序列关键的通用化:如果对象是实际保存的序列,或者可以在迭代工具环境中(如for循环)一次产生一个结果的对象,就看作是可迭代的。总之,可迭代对象包括实际序列和按照需求而计算的虚拟序列。

这个主体中的属于的使用有点随意。“可迭代的”和“迭代器”来表示通常支持迭代的一个对象。有时候,术语“可迭代的”指的是支持iter的一个对象,而“迭代器”值得是iter所返回的一个支持next(I)的对象。

文件迭代器:

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

这种魔法的效果就是,逐行读取文本文件的最佳方式就是根本不要去读取;其替代的办法就是,让for循环在美伦自动调用next从而前进到下一行。

注意,这里的print使用end = ' '来抑制添加一个\n,因为行字符胡茬已经有了一个(如果没有这点,我们输出将会编程两行隔开)。上例是读取文件的最佳方式,原因有三点:这是最简单的写法,运行最快,并且从内存使用情况爱说也是最好的。相同效果的原始方式,是以for循环调用文件的redlines方法,将文件内容加载到内存,做成行字符串列表。

手动迭代:iter和next

python3.0还提供了一个内置函数next ,它会自动调用一个对象的__next__方法。给定一个可迭代对象X,调用next(x)等同于x.__next__(),但前者简单很多。

从技术角度来讲,迭代协议还有一点值得注意。当for循环开始时,会通过它传给iter内置函数,以便从可迭代对象中获取一个迭代器,返回的对象含有需要的next方法。

最初的一步对于文件来说不是必须的,因为文件对象就是自己的迭代器。也就是说,文件有自己的__next__方法,因此不需要像这样返回一个不同的对象。

列表以及很多其他的内置对象,不是自身的迭代器,因为它们支持多次打开迭代器。对这样的对象,我们必须调用Iter来启动迭代:

注意:

从技术上讲,for循环调用内部等价的I.__next__,而不是这里所使用的next(I).这两者之间几乎没有区别,但是,pytyhon3.0中有一些内置的对象(例如os.popen的结果)支持前者而不支持厚泽,但仍然可以在for循环中迭代。手动的迭代通常可以使用任何一种调用形式。

其他内置类型迭代器:

直接的效果是,我们不再需要调用keys方法来遍历字典健--for循环使用迭代协议在每次迭代的时候获取一个健。

迭代协议也是我们必须把某些结果包装到一个list调用中以一次性看到它们的值的原因。可迭代的对象一次返回一个结果,而不是一个实际的列表:

列表解析:初探:

与for循环一起使用,列表解析是最常应用迭代协议的环境之一

列表解析并不完全和for循环语句相同,因为它产生一个新的列表对象(如果有对最初的类标的多个引用,可能会有关系),但是,对于大多数应用程序来说它足够接近,并且是一种足够常见和方便的方法。

列表解析基础知识:

在Python中,大多数人发现列表解析看上去就像一个反向的for循环

列表解析写在一个方括号中,因为它们最终是构建一个新的列表的一种方式。它们以我们所组成的一个任意的表达式开始,该表达式使用我们所组成的一个循环变量(x +10).这后边跟着我们现在应该看作是一个for循环头部的部分,它声明了循环变量,以及一个可迭代对象(for x in L)

要运行该表达式,Python在解释其内不执行一个遍历L的迭代,按照顺序把X赋给每个元素,并且收集各元素运行左边表达式的结果。我们得到的结果列表就是列表解析所表达的内容--包含了x+10 的一个新列表,针对L中的每个X

列表解析一般比手动的for循环语句运行的更快(往往速度会快一倍),因为它们的迭代在解释器内以C语言的速度执行的,而不是以手动Python代码执行的,特别是对于较大的数据集合,这是使用列表解析的一个主要性能优点。

在文件上使用列表解析:

如果我们在表达式中打开它,列表解析将自动使用在本章前面所介绍的迭代洗衣。也就是说,它将会调用文件的next方法,每次从文件读取一行。

Python扫描文件并自动构建了操作结果的一个列表。这也是编写这一操作的一种高效率的方式:因为大多数工作在Python解释器内部完成,这可能比等价的语句要快很多。再次,特别是对较大的文件,列表解析的速度优势可能很显著

扩展的列表解析语法:

作为一个特别有用的扩展,表达式中嵌套的for循环可以有一个相关的if字句,来过滤哪些测试不为真的结果像。

通常我们总是可以把一个列表解析转换为一条for语句。

如果我们需要的还,列表解析可以变得更复杂--例如,它们可能包含嵌套的循环,也可能被编写为一系列的for字句。实际上,它们的完整语法允许任意数目的for字句,每个字句有一个可选的相关的if字句

其他迭代环境:

有时候直到哪些内置工具使用了该协议是很重要的---实现了迭代协议的任何工具,都能够在提供了该工具的内置类型或用户定义的类上自动地工作。

在对象中从左到右扫描的美中工具都使用了迭代协议。这包括我们前面的for循环。然而,列表解析、in 成员关系测试、map内置函数以及像sorted和zip调用这样的内置函数也都使用了迭代协议。

map类似于列表解析,但是它更有局限性,因为它需要一个函数而不是一个任意的表达式。在Python3.0中,它还返回一个可迭代的对象自身,因此,我们必须将它包含到一个list调用中以迫使其一次性给出所有的值。

python还包含了各种处理迭代的其他内置函数:sorted排序可迭代对象中的各项,zip组合可迭代对象中的各项,enumerate根据相对为止来配对可迭代对象中的项,filter选择一个函数为真的项,reduce针对可迭代对象中的成对的项运行一个函数。所有这些都接受一个可迭代的对象,并且在Python3.0中,zip、enumerate、filter也像map一样返回一个可迭代对象。

早先我们也见过内置的dict调用接受一个可迭代的zip结果。为此,我们来看看set调用,以及Python3.0中新的集合解析和字典解析表达式。

实际上,集合解析和字典解析都支持我们前面介绍的列表解析的扩展语法,包括if测试。

python3.0中的新的可迭代对象:

注意sorted对象返回的是一个列表。

range迭代器:

在Python3.0中,它返回一个迭代器,该迭代器根据需要产生范围中的数字,而不是在内存中给建一个结果列表。

python3.0中的range对象只支持迭代、索引以及len函数。它们不支持任何其他的序列操作。

map、zip和filter迭代器:

和range不同,它们都是自己的迭代器---在遍历其结果一次之后,它们就用尽了。换句话说,不能在它们的结果上拥有在哪些结果中保持不同为止的多个迭代器

多个迭代器VS单个迭代器

range支持在其结果上的多个迭代器,这些迭代器会记住它们各自的为止:

相反,zip map 和filter不支持相同结果上的多个活跃迭代器:

当我们后面使用类来编写自己的可迭代对象的时候,将会看到通常通过针对iter调用返回一个新的对象,来支持多个迭代器;单个的迭代器一般意味着一个对象返回其自身。

我们还将看到,在这方面,生成器函数和表达式的行为就像map和zip一样支持单个的活跃迭代器,而不是像range一样。我们还会看到一些暗示:位于循环中的一个单个的迭代器视图多次扫描。

字典视图迭代器:

在Python3.0 中,字典的keys values 和items方法可迭代的视图对象,它们一次产生一个结果像,而不是在内存中一次产生全部结果列表。

视图项保持和字典中的哪些项相同的无力顺序,并且反应对底层的字典作出的修改。

和所有的迭代其一样,我们总可以通过把一个python3.0字典视图传递到list内置函数中,从而强制构建一个真正的列表。然而,这通常不是必须的,除了交互地显示结果或者应用索引这样的列表操作。

此外,python3.0字典荏苒有自己的迭代器,它返回连续的健。

最后,再次提醒,由于keys不再返回一个列表,按照排序的健来扫描一个字典的传统编码模式在python3.0中不在有效。相反,首先用一个list调用来转换keys视图,或者在一个健视图或字典自身上使用sorted调用。

其他迭代其主题:

  • 使用yield语句,用户定义的函数可以转换为迭代的生成器函数。
  • 当编写在圆括号中的时候,列表解析转变为可迭代的生成器表达式
  • 用户定义的类用过__iter__或__getitem__运算符重载变得可迭代。

for循环和迭代器之间的关系:

for循环会使用迭代协议来遍历迭代对象中的每一项。for循环会在每次迭代中调用该对象的__next__方法(有next内置函数运行),而且会捕捉stopIteration异常,从而决定合适停止循环。支持这种模式的任何对象,都可以用于for循环以及其他迭代环境中。

猜你喜欢

转载自blog.csdn.net/qq_34608423/article/details/89472674