What?(Python迭代器是什么?)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)范围内的全部天然数spa
能够看到,MyIter既实现了__iter__()方法,又实现了next()方法,因此MyIter对象既是可迭代对象,又是迭代器对象code
那么这中兼具双重身份的对象与单纯的可迭代对象又有什么区别呢?对象
下面先看以下这个例子,这个例子将MyIter对象与list对象进行了一次比较内存
上图中,方框1&2和方框3&4分别为对MyIter和list对象返回的迭代器进行两次迭代操做的结果,由结果可知,MyIter的迭代器只能进行一次迭代操做,而list的迭代器能够进行屡次迭代操做。string
缘由:这主要是由于兼具双重身份的迭代器对象,每次经过iter()方法返回的都是该对象自身,而后经过该对象自身的next()方法实现遍历操做,因此当执行完一次遍历操做后,该对象的next()函数就到了越界的位置,下次再对该对象进行遍历时,就已经处于越界位置,因此返回结果应该为一个StopIteration异常。而单纯的可迭代对象,每次调用iter()函数时都会返回一个指定的迭代器对象的新实例,因此执行几回iter()方法就会产生几个不一样的迭代器实例,每次迭代时,都是调用不一样的迭代器实例的next()方法返回相应的数据,因此该类可迭代对象就能实现屡次遍历操做。it
验证:本身实现一个单纯的可迭代对象
能够看到,在上面例子中,两次对MyPureIter对象进行迭代,会获得两次迭代结果,这和上面的list的效果是相同的,从而验证了咱们的说法。因此当咱们须要屡次对同一个可迭代对象进行迭代操做时,须要采用这种方式。
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?
使用生成器可以比较方便快速地得到一个迭代器
使用生成器时采用的是惰性生成法则,只有须要时才生成相应的值,这样是内存友好的
生成器表达式有点相似于列表表达式
列表表达式:[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关键字返回一次返回一个结果,经过使用生成器,能够比较方便快捷地得到迭代器对象
生成器表达式与列表表达式很是类似,不过二者的具体使用场景和做用不一样,须要根据具体使用场景选择相信的表达式