Iterator&generator

Iterator(迭代器)

  • 概念

    迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

  • 可迭代对象

    迭代器提供了一个统一的访问集合的接口。只要是实现了iter()或getitem()方法的对象,就可以使用迭代器进行访问。

    例子:

    • 序列:字符串、列表、元组
    • 非序列:字典、文件
    • 自定义类:用户自定义的类实现了iter()或getitem()方法的对象
  • 可迭代对象创建的两种方法

    第一种:

    # 迭代器对象实现了__iter__()方法
    class Fibs:
      def __init__(self):
            self.a = 0
            self.b = 0
        def next(self):
            self.a,self.b = self.b,self.a+self.b
            return self.a
          def __iter__(self):
            return self
    

    __iter__()方法实现了对象可迭代,next()方法实现了迭代。

    第二种:

    # 用iter()工厂类实例化一个可迭代对象
    it = iter([1,2,3])
    it.next()
    
  • 从迭代器中获得序列

    it = iter([1,23,3])
    lits(it)
    

    使用list构造方法显式地讲迭代器转化成列表。

  • 一种更方便的建立迭代器

    # 用括号扩住才是迭代器
    it = (x for x in [2,3,4])
    
    

生成器

  • 概念
    生成器是一种用普通的函数语法定义的迭代器(也叫简单生成器),有点像java中的静态域里面的数据,但用更加灵活。生成器不会把结果保存在一个系列中,而是保存生成器的状态,在每次进行迭代时返回一个值,直到遇到StopIteration异常结束。

  • yield

    在函数中如果出现了yield关键字,那么该函数就不再是普通函数,而是生成器函数。

    yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator。可以用for循环遍历相比于迭代器,生成器更加灵活。

    程序执行到yield后就会返回输出,yield下面的代码会在下次调用next()时运行

  • yield与return

    在一个生成器中,如果没有return,则默认执行到函数完毕时返回StopIteration
    如果遇到return,如果在执行过程中 return,则直接抛出 StopIteration 终止迭代。

    # 不会执行到'b'
    def ge():
      yield 'a'
        return 
      yield 'b'  
    

    如果在return后返回一个值,那么这个值为StopIteration异常的说明,不是程序的返回值。

    # 不会输出'world'
    def ge():
      yield 'hello'
        return 'world'
    

  • 创建一个生成器

    • 简单生成器

      # 简单生成器,一个无穷产生奇数的生成器函数
      def odd():
          n=1
          while True:
              yield n
              n+=2
      
      
    • 循环生成器

      # 循环生成器
      g = ((i+2)**2 for i in range(2, 27))
      

      range()是一个生成器

    • 递归生成器

    # 处理多层嵌套的数据(二维数组等等)
    def flatten(nested):
        try:
            for sublist in nested:
                forelement in flatten(sublist):
                    yield element
      except TypeError:
            yield nested
    list(flatten([1,[2,3],[4,[5,6]],7,8]))
    

    当函数被告知展开一个元素(元素无法展开,一个可迭代对象才能展开 ),for循环会引发一个TypeError异常。但上面的那种情况在处理元素是字符串的时候不适用。

    def flatten(nested):
        try:
            # 不要迭代类似字符串的数据对象
            try:
                nested + ''  # 当nested不是一个字符串的时候会引发一个TypeError
          except TypeError:
                pass
            else: 
                raise TypeError
          for sublist in nested:
                for element in flatten(sublist):
                    yield element
      except TypeError:
            yield nested
            
     # 下面的是可以打印出多层嵌套的数据(无论是一般数据还是字符串)
    def flatten(nested):
        try:
            if isinstance(nested, str):
                raise TypeError
            for sublist in nested:
                for element in sublist:
                    yield element
        except TypeError:
            yield nested
            
    

    • 生成器方法

      • send

        可以改变生成器内部值的方法

        要在生成器挂起后才有意义(也就是说在yield函数第一次被运行之后),如果相对刚刚启动的生成器使用send()方法,可以讲None作为其参数进行调用。

        def repeater(value):
          while True:
          new = (yield value)
          if new is not None:
          value = new 
        # 使用方法
        r = repeater(42)
        r.next()
        r.send('Hello world!')
        
      • throw

        用于在生成器内引发一个异常(在yield表达式中)

        def gen():
          while True:
              try:
                  yield 'normal value'
                  yield 'normal value 2'
                  print 'here'
              except ValueError:
                  print 'we got ValueError here'
              except TypeError:
                  break
        # gen()用法
        g - gen()
        print next(g)
        print g.throw(Valueerror)
        print next(g)
        print g.throw(TypeError)
        
        """
        程序的输出:
        print(next(g)):会输出normal value,并停留在yield ‘normal value 2’之前。
        由于执行了g.throw(ValueError),所以会跳过所有后续的try语句,也就是说yield ‘normal value 2’不会被执行,然后进入到except语句,打印出we got ValueError here。然后再次进入到while语句部分,消耗一个yield,所以会输出normal value。
        print(next(g)),会执行yield ‘normal value 2’语句,并停留在执行完该语句后的位置。
        g.throw(TypeError):会跳出try语句,从而print(‘here’)不会被执行,然后执行break语句,跳出while循环,然后到达程序结尾,所以跑出StopIteration异常。
        """
        
      • close

        它在yield运行处引发一个GeneratorExit异常,可以对生成器内进行代码清理,一般讲yield语句放在try/finally语句中。执行close()方法后,生成器对象就会被销毁,不能再调用next()方法

        def gen():
          yield 1
          yield 2
          yield 3
          
        g = gen()
        print next(g)
        g.close()
        next(g)
        

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容