您的位置:首页 > 编程语言 > Python开发

Python学习笔记--迭代器&生成器

2016-05-08 00:00 661 查看

一、Python迭代器

What?(Python迭代器是什么?)
在使用Python进行编程时,经常会使用for语句对一个对象进行遍历,获取所需数据,如
li = [1, 2, 3, 4, 5]
for i in li:
print i
像list、dict、string这一类可以使用for语句直接进行遍历的对象,称之为可迭代对象(Iterable),所谓可迭代对象,即为一类实现了__iter__()方法的对象,这类对象通过__iter__()方法返回一个迭代器,从而实现迭代操作;而所谓的迭代器对象(Iterator),即为一类实现了next()方法的对象,这类对象通过next()方法在一定范围内返回用户所期望的数据,超出范围则抛出StopIteration异常,并终止迭代

How?(如何创建并使用迭代器对象?)
下面这段代码自定义了一个迭代器对象MyIter,通过遍历该对象,可以获得[0, n)范围内的所有自然数



可以看到,MyIter既实现了__iter__()方法,又实现了next()方法,所以MyIter对象既是可迭代对象,又是迭代器对象
那么这中兼具双重身份的对象与单纯的可迭代对象又有什么区别呢?
下面先看如下这个例子,这个例子将MyIter对象与list对象进行了一次比较



上图中,方框1&2和方框3&4分别为对MyIter和list对象返回的迭代器进行两次迭代操作的结果,由结果可知,MyIter的迭代器只能进行一次迭代操作,而list的迭代器可以进行多次迭代操作。
原因:这主要是因为兼具双重身份的迭代器对象,每次通过iter()方法返回的都是该对象自身,然后通过该对象自身的next()方法实现遍历操作,所以当执行完一次遍历操作后,该对象的next()函数就到了越界的位置,下次再对该对象进行遍历时,就已经处于越界位置,所以返回结果应该为一个StopIteration异常。而单纯的可迭代对象,每次调用iter()函数时都会返回一个指定的迭代器对象的新实例,所以执行几次iter()方法就会产生几个不同的迭代器实例,每次迭代时,都是调用不同的迭代器实例的next()方法返回相应的数据,所以该类可迭代对象就能实现多次遍历操作。
验证:自己实现一个单纯的可迭代对象


可以看到,在上面例子中,两次对MyPureIter对象进行迭代,会得到两次迭代结果,这和上面的list的效果是相同的,从而验证了我们的说法。所以当我们需要多次对同一个可迭代对象进行迭代操作时,需要采用这种方式。

二、Python生成器

What?
Python生成器是一个能有快速创建迭代器的强有力的工具。生成器看上去和普通函数类似,但是当需要返回数据时,使用yield关键字进行声明,而非return关键字。每次调用生成器的next()函数时,生成器会返回yield关键字后面的内容,并记住这次的返回位置和函数内部变量状态,用于下一次调用时进行恢复。

How?

创建生成器
下面的示例演示了通过yield关键字生成一个迭代器的过程


生成器的特点

生成器会自动生成迭代器的__iter__()方法和next()方法

在两次调用间函数的执行状态和局部变量会自动保存

生成器的执行流程

第一次调用:i=0, yield i,返回0,保存变量i的值0及这次函数执行的位置

第二次调用:恢复函数状态i=0,i += 1, 从而i=1,返回1,保存变量i的值1及这次函数执行的位置

。。。

第五次调用:恢复函数状态i=3,i += 1, 从而i=4,返回1,保存变量i的值1及这次函数执行的位置

第六次调用:恢复函数状态i=4,i += 1, 从而i=5,i>=n,函数结束

Why?

使用生成器能够比较方便快速地获得一个迭代器

使用生成器时采用的是惰性生成法则,只有需要时才生成相应的值,这样是内存友好的

三、Python生成器表达式

生成器表达式有点类似于列表表达式

列表表达式:[expr for i in iterable if cond_expr](下面左图)

生成器表达式:(expr for i in iterable if cond_expr)(下面右图)





列表表达式与生成器表达式:

两者的写法不同,前者是中括号,后者是小括号

两者返回的值不同,前者返回一个列表,后者返回一个生成器

两者的作用不同,前者可以进行重复操作,多次迭代;后者只能进行一次迭代

后者比前者更加内存友好,所以当每次只需要返回一个值,并且不需要进行重复操作时,应该使用生成器表达式;而当一次需要使用列表中多个值,或者需要对列表元素进行多次操作时,则需要使用列表表达式

四、总结

Python迭代器是一类实现了__iter__()方法和next()方法的对象

对于一个可迭代对象,for语句可以通过iter()方法获得该对象的迭代器对象,然后通过迭代器对象的next(0方法依次获得想要的元素

当可迭代对象同时也是迭代器对象时,无法进行独立的迭代操作;而像list这类可迭代对象,其迭代器对象是独立存在的,这时就可以重复进行迭代操作

生成器是一类特殊的函数,这类函数不通过return语句返回值,而是通过yield关键字返回一次返回一个结果,通过使用生成器,可以比较方便快捷地获得迭代器对象

生成器表达式与列表表达式非常相似,不过两者的具体使用场景和作用不同,需要根据具体使用场景选择相信的表达式
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息