Python 迭代器的概念

使用迭代器的理由:

1、“流式”数据处理方式减少内存消耗

比如处理文件,一下猛地把全部数据全部取出来放到内存里面进行处理会导致程序消耗大量内存

有时甚至没法做到,

一般我们会一部分一部分的对文件内容进行处理:

for text_line in open("xx.txt"):
  print text_line

open("xx.txt")返回的是可迭代的对象,所以,可以渐进式地对文件的内容进行处理,即按行来读取文件,并进行处理,而不是,

直接把全部文件一下加载到内存中

2、支持方便用for语句对数据进行处理

python内置的一些常见的像类型像数组、列表甚至字符串等都是可迭代类型

这样我们就能方便for语句这个语法方便对数据进行消费,不需要自己记录索引位置,人肉循环

for i in [1, 2, 3, 4]
  print i,

迭代器的内部实现:

可迭代对象迭代器对象:

可迭代对象对象里面包含__iter()__方法的实现,对象的iter函数经调用之后会返回一个迭代器,

里面包含具体数据获取的实现

迭代器:包含有next方法的实现,在正确范围内返回期待的数据以及超出范围后能够抛出StopIteration的错误停止迭代。

可以直接作用于for循环的数据类型有以下几种:

一类是集合数据类型,如listtupledictsetstr等;

一类是generator,包括生成器和带yield的generator function。

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

可以使用isinstance()判断一个对象是否是Iterable对象:

from collections import Iterable
print isinstance('abc', Iterable)
print isinstance((x for x in range(10)),Iterable)

迭代器不但可以作用于for循环,还可以next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator

生成器都是Iterator对象,但listdictstr虽然是Iterable,却不是Iterator

listdictstrIterable变成Iterator可以使用iter()函数:


正式的说法:一个实现了__iter__方法的对象是可迭代的,一个实现next方法的对象则是迭代器

我的理解:可迭代对象中包含了迭代器(__iter__返回一个迭代器),迭代器是核心,

也是一个数据生成器

因为计算过程是可迭代的,才可以使用迭代器,相当于只要有了初始值,和迭代的公式,

就可以计算出任何值

所以,迭代器的实现,在__init__()里可以实现初始化,在next()里实现迭代的公式和返回值,

并达到迭代终点后抛出StopIteration异常。

迭代器相当于把迭代的过程封装到类里面

举例:

计算斐波那契数列数列就是一个迭代的过程:

我们先实现其迭代器:迭代器,就是将迭代的过程封装成类,也就是1、初始化数据 2、实现迭代的公式

class FibIter:
    def __init__(self):
        self.a = 0 
        self.b = 1 

    def next(self):
        self.a,self.b = self.b,self.a+self.b
        if self.a>10:
            raise StopIteration()
        return self.a

然后定义可迭代的对象:可迭代的对象有__iter__:方法,返回一个迭代器

class Fib:
    def __init__(self):
        pass
    def __iter__(self):
        return FibIter()

for 循环可以用来遍历可迭代的对象,迭代器可以看做是数据生成器,也就是可迭代的对象可以看成是数的集合,next()都会返回一个结果

for f in Fib():
    print f

结果:

1
1
2
3
5
8
分析:

  1. 数据确实是“流式”处理的
  2. iterator是真正在背后做事的人
  3. for语句能够非常方便的迭代对象的数据。
可迭代对象其实更像是整个迭代器模式模式的上层,像一种约束一种契约一种规范,它能够保证自己能
够返回一个在实际工作中干活的迭代器对象
forsum等接受一个可迭代对象的方法都是遵循这样的规范:
调用对象的__iter__函数,返回迭代器对迭代器对象返回的每个值进行处理抑或需要一些汇总的操作。
for举个例子:

for的运行机理:可以用如下代码来仿真:

for这个语法背后的逻辑:首先获取可迭代对象返回的迭代器对象,然后调用迭代器对象的next方法获取每个值,

在获取值的过程中随时检测边界-也就是检查是否抛出了StopIteration这样的错误,

如果迭代器对象抛出错误则迭代停止

Python的for循环本质上就是通过不断调用next()函数实现的

iter = Fib().__iter__()
while True:
    try:
        value = iter.next()
    except StopIteration:
        break
    print value

当然了,一般在应用过程中我们不会将他们特意的分开,我们能够稍微对迭代器对象进行修改一下,

添加__iter__方法的实现,

这样对象本身就既是可迭代对象也是一个迭代器对象了:

class Fib:
    def __init__(self):
        self.a = 0 
        self.b = 1 

    def next(self):
        self.a,self.b = self.b,self.a+self.b
        if self.a>10:
            raise StopIteration()
        return self.a
    def __iter__(self):
        return self

for f in Fib():
    print f


从迭代器得到序列,迭代器可以生成数据,相当于把迭代器生成的数据全部收集到序列中

print list(Fib())


总结:

这是因为Python的Iterator对象表示的是一个数据流Iterator对象可以被next()函数调用并不断返回下一个数据直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

即迭代器可以作为一个数据生成器





  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值