与其他高级语言一样,Python也提供了迭代器的功能,迭代器统一了访问的集合的方式,Python中所有的集合数据类型(list, str, dict, set, tuple)都支持使用for进行迭代,当然我们也可以为自己定义的类或函数实现这种迭代的功能
例子
我们先来看一个例子,我们生成一个斐波那契序列
1 | def fabs(count): |
上面在函数里面直接print结果,显然这样做的复用性特别差,于是我们想到了用列表
1 | def fabs(count): |
使用list返回可以解决了复用性问题,但是有时候我们需要使用的数据量非常大的时候,返回整个list会占用大量内存,这个时候,我们希望,函数返回的值不要一次性全部返回,而是用到的时候计算再返回,这样数据量再打也只占用一份内存而已了,Python提供了两种方式实现这种逐步迭代的方式,于是就有了下面迭代器和生成器
迭代器
迭代器统一了所有集合访问元素的方式,包括有序无序的,相比for遍历集合,其支持随机访问的集合,如set
,dict
,只能向前,不能后退,迭代器有下面两个基本方法,大多数高级语言都会定义统一的迭代器操作,Python中的迭代器类型需要实现下面两个方法
next
:返回迭代器下一个元素__iter__
方法:返回一个迭代器
给一个类实现迭代器功能,生成斐波那契序列
1 | class Fabs(object): |
生成器yield
上面我们看到每次迭代通过调用next取得值,Python还提供了另一个关键字yield用于更方便的迭代每个值,C#也支持这种语法,带有yield关键的函数被称为生成器(generator)
yield:在函数使用yield返回每次迭代的值,而不直接返回,yield返回值后等待下次迭代,而保留当前的状态(局部变量不变),直到下次迭代的时候,接着后面的代码继续执行
1 | def Foo(): |
- 上面函数Foo可以迭代三次,分别返回1,3,2,与普通的列表一样
- 使用了生成器的函数,不能使用return,编译器会报错
- 生成器返回的对象是
generator
- 生成器在迭代完最后一个值之后,当迭代函数执行完,没有yield返回迭代值的话,会抛出StopIteration异常表示迭代结束
- 只有生成器调用
next
方法的时候才会运行迭代过程
生成器支持与外部函数交互send
生成器可以通过yield返回值给外部函数,也可以接受外部函数传递的值,通过send
方法传值
1 | for _ in test(): |
迭代器每次迭代实际上相当于调用了next方法,然后从yield取值,Python迭代器还提供了send方法,功能与next类似,但是可以传递参数作为yield的返回值在迭代器内部使用
1 | def test(): |
yield的原理
//TODO: