zoukankan      html  css  js  c++  java
  • python 生成器&迭代器

     

    一、生成器

    1、列表生成器:列表生成式就像是一个厨师,他只会做这n(n为任意整数)道菜,想吃甚麽做甚麽,不吃不做,不浪费空间;而列表表达式就相当于已经做好的n盘菜,占用空间。
    2、生成器的创建方法:

    • s = (x*2 for x in range(5))
    • yield+数字     只要有yield就是一个生成器对象

    注意:生成器在创建的时候已经决定了能计算出值得个数,调用next的个数一旦超过这个值就会报错

       第一种:

    s = (x*2 for x in range(5))
    
    # 生成器的调用方法:next()
    print(next(s)) # 提取生成器里面的值,in python2中等价于 s._next_(),next() 一次打印一次
    print(next(s))
    print(next(s)) # 生成器就是一个可迭代对象(Iterable) for i in s: # 遍历生成器可迭代对象 print(i) # 打印完一个数之后这个数就被回收,不占用内存,只占用被引用值的哪一个内存

    >>> 0  2  4  6  8

    运行机制:从0开始,第一次next()时,取出一个数*2输出,然后每next()一次,取一个数,一直到2,for循环遍历时,因为前面next()已经取到了数字2的位置,所以从3开始,故输出为0 2 4 6 8

       第二种:

    def fun():         # 注意:生成器对象是fun(),而不是fun
        print('s')
        yield 1
    
        print('ss')
        yield 2
    
    g = fun()
    print(g)           # <generator object fun at 0x000001D54E12A0F8>
     
    next(g)            # 有返回值,为yield后的值
    next(g)

    解释:程序运行时先执行g = fun(), 执行到第一个next()时,返回到函数中执行具体内容,一直到执行完yield 1 停止,然后继续下一个next()再到函数中寻找yield 2 的内容,以此类推注意:如果再多一个next(g)就会报错:StopIteration(停止迭代),因为超过了迭代次数

    什么是可迭代对象:内部有 _iter_() 的都是可迭代对象(列表、元组、字典)

    def fun():   
        print('s')
        yield 1
    
        print('ss')
        yield 2
    
    for i in fun():
        print(i)       # yield 有返回值,返回值赋给了i

    >>>

    s
    1
    ss
    2

    例1:输出斐波那契数列

    def fib(maxs):
        n, before, after = 0, 0, 1
        while n < maxs:
            print(after)       # 从1开始,如打印before则从从0开始
            before, after = after, before+after      # 先计算后赋值(先右后左)
            n = n+1
    
    fib(10)     # 输出前10个斐波那契数

    注意:before, after = after, before+after  和 下面的两条语句不等价,原因见例1对应标注;

    before = after
    after =  before+after

    例2:斐波那契数列生成器

    def fib(maxs):
        n, before, after = 0, 0, 1
        while n < maxs:
            yield before
            before, after = after, before+after      # 先计算后赋值(先右后左)
            n = n+1
    
    g = fib(8)
    print(g)     # 生成器所在的内存地址
    
    # 需要几个next() 几次,但最多不能超过8次,否则应修改fib() 里面的数字
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))

    3、 .send() 方法

    def fun():        # fun()是一个生成器对象而不是fun
        print('qwer')
        count = yield 1  # 先把yield的值返回,然后把‘xss’赋值给变量count
        print(count)
    
        print('asdf')
        yield 2
    
    f = fun()
    # next(f)      # 进入函数体
    f.send(None)   # 等价于next(f)  
    
    s = f.send('xss')   # 给yield前面的变量赋值
    print(s)    
    # s 是yield 2 的返回值

      注意:第一次send前如果没有next,只能传一个send(None),否则报错,TypeError: can't send

    non-None value to a just-started generator,第一次通过进入send(None) 进入函数之后首先执行

    print(),yield返回一个1,再次进入之后就把send()里面的值传给count,然后就可以对count进行操作

    例3:yield 伪并发的实现

    import time
    
    def consumer(name):
        print("%s准备吃包子!" % name)
        while True:
            baozi = yield
            print("包子[%s]来了,被[%s]吃了!" % (baozi, name))
    
    def producer(name):
        a1 = consumer('A')
        a2 = consumer('B')
        next(a1)
        next(a2)
        print("%s准备吃包子了!" % name)
        for i in range(5):
            time.sleep(1)
            print("做了2个包子")
            a1.send(i)
            a2.send(i)
    
    producer("xiaoss")

    >>>

          A准备吃包子!
          B准备吃包子!
          xiaoss准备吃包子了!
          做了2个包子
          包子[0]来了,被[A]吃了!
          包子[0]来了,被[B]吃了!
          做了2个包子
          包子[1]来了,被[A]吃了!
          包子[1]来了,被[B]吃了!
          做了2个包子
          包子[2]来了,被[A]吃了!
          包子[2]来了,被[B]吃了!
          做了2个包子
          包子[3]来了,被[A]吃了!
          包子[3]来了,被[B]吃了!
          做了2个包子
          包子[4]来了,被[A]吃了!
          包子[4]来了,被[B]吃了!

    二、迭代器

    1、什么是迭代器?

        迭代是指可以用for循环来遍历

         for循环内部三件事: 1.调用可跌代对象的iter方法返回一个可迭代对象
                                            2.不断调用可迭代对象的next方法
                                            3.处理StopIteration

      处理StopIteration的过程如下:

    while:
        try:
            I = next(list_Iterator)
        
        except StopIteration:
            break

      注:生成器都是迭代器,迭代器不一定是生成器

    2、满足两个条件: (1)有iter方法  (2) 有next方法   

    from collections import Iterable,Iterator   # 调用Iterable和Iterator
    
    lis = [1, 2, 3, 4]
    d = iter(lis)   # 相当于 l._iter_()
    print(d)        # <list_iterator object at 0x00000206700DC358>
    print(next(d))
    print(next(d))
    print(next(d))
    print(next(d))
    
    for i in [1, 2, 3, 4]:
        iter([1, 2, 3, 4])
    
    print(isinstance([1, 2], list))    # 判断一个字符是不是某个特定的数据类型 isinstance(数据, 数据类型)
    print(isinstance(lis, Iterable))   # 判断lis是不是迭代器

    >>>

    <list_iterator object at 0x000002756B321240>
    1
    2
    3
    4
    True
    True

    例1:用迭代找出文档中最长的行

    F = max(len(x.strip()) for x in open('file_1', 'r'))      # 文件读取,找出最长的行
    print(F)       # 最长行字符的个数
  • 相关阅读:
    python初学者学习工具安装教程&安装步骤详解
    Django面试题
    数据库-面试题
    Python面试题
    Python 内置函数&filter()&map()&reduce()&sorted()
    Python匿名函数(lambda函数)
    Python中两大神器&exec() &eval()
    面向对象&从这里开始我们将不再是纯小白
    软件开发程序猿日常必备,现用现查&日志记录
    如何去写项目的readme&链接
  • 原文地址:https://www.cnblogs.com/ss-long/p/10413616.html
Copyright © 2011-2022 走看看