python学习笔记——生成器和迭代器

一、生成器

  1. 计算机的储存资源一向是很宝贵的,在对大量的数据进行计算时,如果是把数据统一读到内存中来在进行计算就会造成大量的资源浪费。用生成器来进行算计时采用是一边循环一边计算的方式,不用一下将数据读入内存,节约大量内存空间。
  2. 举个简单的列子说明:
    • 生成一个列表,并输出列表各项乘以2的值,可用 [i*2 for i in range(10)]  来实现.
    • 当上个语句改为 (i*2 for i in range(100)) 时就成为了一个生成器,只有当循环到第i个值的时候i的数据才生成并被计算,且生成器只记住当前位置无法查询前一个数值。
  3. 生成器只有两种调用方式
    c = (i*2 for i in range(100))  # 计算100个随机数乘以2的值
    for i in c:  # 利用循环调用生成器
        print(i)
    
    print('------other method-------')
    for i in range(100):
        n = c.__next__()  # 使用c.__next__()语句调用生成器,当生成器本身有输出时常用此种调用方式
        print(n)
  4. 当数据复杂时可利用函数构成生成器,需要使用yield作为函数的输出或者返回值,一个小例子,斐波那契数列,从第三个数开始后一个数等于前两数之和
    # ########利用函数实现累加#########
    def fib(max):
        n, a, b = 0, 0, 1
        while n < max:
            print(b)  # 输出每次累加的值
            a, b = b, a+b  # a=b,b=a+b相当于t=(b,a+b),t(0)=a,t(1)=a+b,用于累加
            n = n+1
    
    
    fib(10)  # 设定循环次数为10,并调用函数
    
    # ##########构成生成器##########
    print('-------product-------')
    
    
    def fib(max):
        n, a, b = 0, 0, 1
        while n < max:
            yield b   # 返回当前值并暂停运算,yield
            a, b = b, a+b  # a=b,b=a+b相当于t=(b,a+b),t(0)=a,t(1)=a+b,用于累加
            n = n+1
    
    
    c = fib(10)  # 将函数赋成的生成器赋值于变量
    for i in c:  # 唤醒生成器
        print(i)  # 输出每次累加的值
  5. 上述生成器可加入return语句作为抓取异常的返回信息,以上数程序举例,当使用print(c.__next__())调用生成器时超过了生成器的循环值会报StopIteration(异常停止)的错,可使用下列程序抓取错误并处理
    def fib(max):
        n, a, b = 0, 0, 1
        while n < max:
            yield b   # 返回当前值并暂停运算
            a, b = b, a+b  # a=b,b=a+b相当于t=(b,a+b),t(0)=a,t(1)=a+b,用于累加
            n = n+1
        return '-----done'  # 出现异常时打印消息
    
    
    c = fib(10)  # 将函数赋成的生成器赋值于变量
    print(c.__next__())  # 调用超过10次的错误操作
    print(c.__next__())
    print(c.__next__())
    print(c.__next__())
    print(c.__next__())
    print(c.__next__())
    print(c.__next__())
    print(c.__next__())
    print(c.__next__())
    print(c.__next__())
    print(c.__next__())
    g= fib(6)  # 调用函数并传递参数
    while True:  # 建立死循环不断抓取
        try:
            x = next(g)
            print('g:', x)
        except StopIteration as e:  # 遇到StopIteration错误将它命名为e
            print('StopIteration return value', e.value)  # 打印错误信息,及return的值
            break
  6. 单线程的生成器并行,代码说明
    # ########单线程生成器并行########
    import time
    
    
    def consumer(name):
        print("%s要吃面" % name)
        while True:
            mian = yield  # 程序运行暂停,等待再次被唤醒执行下面的代码
            print('%s面来了,被%s吃光了' % (mian, name))
    
    
    c = consumer('mina')
    c.__next__()  # 唤醒生成器
    
    # ######c.send(参数)可在唤醒生成器的时候将参数传递给yield###########
    
    
    def producer(name):
        c1 = consumer('A')
        c2 = consumer('B')
        c1.__next__()
        c2.__next__()
        print('%s开始下面' % name)
        for i in range(10):
            time.sleep(1)
            print('下了1碗面')
            c1.send(i)  # 唤醒生成器并将i的值传递给yield
            c2.send(i)
    
    
    producer('minax')

     此时应注意c.send()只适合于并行时使用

二、迭代器(Iterator)

  1. 可迭代对象:可直接作用于for循环的对象统称为可迭代对象,并且可使用isinstance(self,TIterable)判断对象是否可迭代。
    from collections.abc import Iterable  # 将Iterable模块导入,3.8版本使用,之前的版本为from collections import Iterable
    print(isinstance((x for x in range(10)), Iterable))  # 结果为True
  2. 迭代器:可以被next()函数调用并不断返回下一个值的对象称为迭代器
    d = (x for x in range(10))  # 一个迭代器
    print(next(d))  # 输出0
    print(next(d))  # 输出1
  3. 字典、列表、字符串、元组等可用iter()变为迭代器
    from collections.abc import Iterable  # 将Iterable模块导入,3.8版本使用,之前的版本为from collections import Iterable
    c = [1, 2, 3, 4]
    iter(c)
    print(isinstance(c, Iterable))

三、内置参数/方法

  1. 匿名函数,即可不用命名函数
    call = lambda n: print(n)  # 相当于{def s(n): print(n)}s(5)
    call(5)
    
    (lambda n:print(n))(5)  # 另一种设置方式
  2. 过滤,例如过滤出大于5的列表,可利用匿名函数
    a = filter(lambda n: n > 5, range(1, 10)) # n从1到10依次取大于5的值
    c = list(a)  # 可用list得到filter过滤器返回的一个可迭代对象
    print(c)  # 结果为[6, 7, 8, 9]
  3. 按指定方式处理值,即map的使用,与过滤相似
    c = map(lambda n: n*n, range(10))  # 使用map按指定方式处理n值
    print(list(c))  # 输出[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

     另一种,使用function标准库,如计算阶乘,需使用两个变量

    import functools  # python3.8里用的functools,以前版本好像是用的function来着
    
    reg = functools.reduce(lambda x, y: x*y, range(1, 10))  # 实现阶乘
    print(reg)  # 输出为362880

四、json序列化模块,将字典、列表等转为字符串存入文件,也可以反向运行

  1. 代码说明
    # ##########json##########
    import json
    
    info = {
        'name': 'mina',
        'age': 18
    }  # 定义一个字典
    with open('test.text', 'w') as f:  # 以写模式创建一个文件
        f.write(json.dumps(info))  # 将字典利用json模块写入文件中,结果为{"name": "mina", "age": 18}

     将文件中的字符串转为对应字典或数组

    with open('test.text', 'r') as c:  # 以读模式打开文件
        data = json.loads(c.read())  # 将文件中的字符串下载并转为字典
    print(data['name'])  # 利用字典的查询方式输出‘mina’

猜你喜欢

转载自www.cnblogs.com/minax/p/9949218.html