Python中yield关键字与迭代器

来源:互联网 发布:2017男女比例真实数据 编辑:程序博客网 时间:2024/06/07 21:24
    本文主要是参考网络文章所作的一些学习笔记,谈不上原创,主要学习的文章如下所示:

    http://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/(非常感谢,除了技术方面,还对如何撰写技术文章有启发)

    http://www.cnblogs.com/cacique/archive/2012/02/24/2367183.html

    http://www.jb51.net/article/15717.htm

 

    1. 什么是迭代器?

        迭代器可以由调用迭代器函数生成(其中一种方式),以yield关键字的生成器为例,在函数的执行过程中,yield语句会把你需要的值返回给调用生成器的地方,然后退出函数,下一次调用生成器函数的时候又从上次中断的地方开始执行,而生成器内的所有变量参数都会被保存下来供下一次使用。

 

2.为什么如下的函数,迭代器第一次调用send函数时,为什么不能传递参数:

   

现在,我们来揭晓yield的工作原理。我们知道,我们上面的h()被调用后并没有执行,因为它有yield表达式,因此,我们通过next()语句让它执行。next()语句将恢复Generator执行,并直到下一个yield表达式处。比如:
def h():
    print 'Wen Chuan'
    yield 5
    print 'Fighting!'

c = h()
c.next()c.next()调用后,h()开始执行,直到遇到yield 5,因此输出结果:
Wen Chuan

(详细出处参考:http://www.jb51.net/article/15717.htm)

我们可以把 yield 想象成下面的伪代码:

x = yield i ==> put(i); x = wait_and_get(),那么h()函数可以改写成:

 

def h():    print "WenChuan"    puts(5)#第一个next() 程序执行到这里就停止了    wait_and_get()    print 'Fighting!'

    第一次调用send()或者next()函数,send函数不能带参数,因为到puts(5)为止,没有wait_and_send()函数接收参数,第二次调用send()函数并传递一个参数,才有wait_and_get()函数接收传递进来的参数。

 

3. 定义迭代器类或者迭代器函数

    迭代器类:调用__itter__(self),   在python中,要想你的自定义类型能产生一个iterator object有两种方法,一种是借用现有的序列容器或者iterator对象,在你自己类中定义__iter__方法并返回一个iterator对象。另一种方法是,在__iter__中返回self,并定义一个next()方法,这样你就可以不借助于任何其它iterator,你的类对象将是一种元iterator对象。

#! /usr/bin/env pythonclass Fab(object):     def __init__(self, max):         self.max = max         self.n, self.a, self.b = 0, 0, 1     def __iter__(self):         return self     def next(self):            if self.n < self.max:                 r = self.b                 self.a, self.b = self.b, self.a + self.b                 self.n = self.n + 1                 return r             raise StopIteration        if __name__ == '__main__':    fab = Fab(10);    for i in fab:        print i,

或者

>>> class it():  def __init__(self):    self.ls = [1,2,3]  def __iter__(self):    return iter(self.ls)>>> its = it()>>> for i in its: print i

   

range与xrange:

range返回一个列表,而xrange返回一个可迭代对象,在节省内存方面更有优势,我自己写的,类似于xrange的类如下所示:

#!/usr/bin/env pythonclass xRange():    def __init__(self, start, end):        self.start = start        self.end = end            def __iter__(self):        return self        def next(self):        if self.start < self.end:            i = self.start            self.start += 1            return  i        raise StopIteration()    def main():    x = xRange(1,8)    for item in x:        print item        if __name__ == '__main__':    main()    


 

原创粉丝点击