美文网首页
10.迭代器与生成器

10.迭代器与生成器

作者: 哈哈大圣 | 来源:发表于2019-12-21 15:47 被阅读0次

    一、迭代器

    1). 迭代器概述

    1. 类比Java中的迭代器,参考迭代器模式https://www.jianshu.com/p/ee999431fb92
    2. 被迭代对象对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个Stoplteration异常,以终止迭代
    3. 迭代只能向前。
    4. 可迭代对象:实现了迭代器的对象(调用内部定义一个iter()方法,实现迭代器功能,创造迭代器对象) (类比Java中的接口)
    5. 字符串、列表、元组、字典、集合、文件对象这些不是可迭代对象,但使用for遍历的时候调用了他们内部的iter方法生成了迭代器。
    6. 使用转换str(t),list(),int(),tuple(),dict(),set()等也使用迭代器

    2). 迭代器使用

    1. 判断一个对象是否可迭代
    from collections import Iterable
    a = isinstance("", Iterable)
    b = isinstance({}, Iterable)
    c = isinstance([], Iterable)
    d = isinstance((), Iterable)
    
    # True
    
    1. 生成迭代器
    a = "abc".__iter__()
    # 或者
    b = iter("abc")
    
    1. 判断一个对象是否为一个迭代器
    from collections import Iterator
    
    # 调用iter()方法将可迭代对象转换成迭代器
    a = isinstance("abc".__iter__(), Iterator)  
    
    1. 迭代器使用常用方法 (假设t为迭代器)

      • t.__next__(): 返回下一个迭代元素
      • next(t): 同理,返回下一个迭代元素
      • t.send("****"):配合函数中的yield使用
    2. for循环的原理

    l = [1, 2, 3]
    for i in l:
        print(i)
    
    # 内部实现如下
    iter_test = l.__iter__() # iter_test = iter(l)
    print(iter_test)
    print(iter_test.__next__())
    print(iter_test.__next__())
    print(iter_test.__next__())
    print(iter_test.__next__()) # 这里就抛出异常
    
    1. 文件句柄中使用迭代器
    with open('test.txt', 'r+') as f:
        for i in f:
            print(i, end="") # end参数表示打印结束为换行符
    

    使用for遍历文件,可以减少不必要的内存空间占有率

    • 补充,获取对象的属性
    n = "hahadasheng"
    b = dir(n)
    print(b)
    

    二、生成器

    1). 概述

    1. 生成器(generator object):动态生成下一个元素,按需生产。
    2. 直接使用object._next_(),无需调用__iter__()方法
    3. 生成器就是可迭代对象,延迟计算,一次返回一个结果(利于大数据处理)
    4. 一个生成器只能遍历一次,生成器在产生的时候只是返回生成器地址,当遍历的时候调用_next_()方法,位置才发生变化

    2). 生成器的一般使用

    1. 列表生成式:range函数,动态生成数据
    for i in range(0, 101):
        print(i)
    
    1. 函数生成器:生成斐波那契数列
    def fib(max):
        n, a, b = 0, 0, 1
        while n < max:  # 计算n次
            yield b     # 将函数的执行过程冻结在这一步,并且将b的值返回给next(),相当于return
            a, b = b, a + b
            n += 1
        return "done"
    
    # 这时函数并没有执行,而是返回了一个生成器,注意:不需要使用f.__iter()__; 
    f = fib(15)  
    for i in f:  # f.__next__() 也是可以的
        print(i)
    
    1. 函数生成器:向函数中传值
      • send的作用: 唤醒并执行、发送一个信息到生成器内部(默认发送None,可以在函数内部根据传送的信号确定执行状态,比如用if进行判断是否终止)
      • next(?)?.__next__()?.send(?):这三个都能唤醒生成器继续工作。
    def test():
        print("run 1")
        x = yield 1
        print(x)
        yield 2
    
    g = test()           # 获得生成器
    a = g.__next__()     # 生成器开始执行 到yield 1并挂起,并将1返回
    print(a)
    b = g.send("haha")   # 将值传递给x;同时获得穿回来的值
    print(b)
    
    1. 案例:用函数实现range功能
    def range2(n):
        count = 0
        while count < n:
            print("func: %s" % count)
            print(count)
            count += 1
            sign = yield count  # 返回数据count,中断程序,当外部调用next(),继续执行函数有了yield加括号,
            print("---sign",sign)  # 就成了一个生成器,如果有并执行到return 在生成器中,代表生成器的终止,直接走到报错
            
    new_range = range2(10) #产生了一个生成器 print(new_range)
    new_range.__next__()
    new_range.__next__() #next唤醒并继续执行,相当于给生成器发送了一个None
    new_range.send("stop")
    

    3). 三元表达式

    1. 语法
    结果 = value1 if 条件成立就返回value1,如果不成立就返回value2 else value2
    
    1. 案例
    name='晓庆'
    res = '女神' if name == '晓庆' else '不是女神'
    print(res)
    
    1. 生成器-三元表达式:写到列表和元组里面,按需生产
    a = [i if i % 2 == 0 else None for i in range(10)]
    print(a) # [0, None, 2, None, 4, None, 6, None, 8, None]
    

    4). 列表解析 (直接动态生成列表)

    l1 = ['鸡蛋%s' %i for i in range(10)]  #二元
    # ['鸡蛋0', '鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4', '鸡蛋5', '鸡蛋6', '鸡蛋7', '鸡蛋8', '鸡蛋9']
    
    l2 = ['鸡蛋%s' %i for i in range(10) if i > 5 ] #三元 生成一个列表
    # ['鸡蛋6', '鸡蛋7', '鸡蛋8', '鸡蛋9']
    
    # 没有四元表达式
    # l3 = ['鸡蛋%s' %i for i in range(10) if i > 5 else i]  
    
    

    5). map、sum、min、max迭代器

    l = [1, 2, 3, 3, 4]
    s = map(lambda x: x**x, l)
    print(sum(s))
    
    
    print(sum(i for i in range(1000)))
    

    6). 生成器 + lambda + 函数闭包 + 延迟执行

    import copy
    def a():
        # 闭包延迟, 返回的为4个匿名函数,但是在执行时i都为3
        a, b, c, d = [lambda x: copy.copy(i) * x for i in range(4)]
        print(a(2), b(2), c(2), d(2)) # 6 6 6 6
        
        # 设定局部变量,匿名函数中的i分别为 0 1 2 3
        e, f, g, h = [lambda x, i = i: copy.copy(i) * x for i in range(4)]
        print(e(2), f(2), g(2), h(2)) # 0 2 4 6
    
        # 这里返回的也为延迟,i 统统为 3
        return [lambda x:copy.copy(i) * x for i in range(4)]
    
    print([m(2) for m in a()])
    
    

    相关文章

      网友评论

          本文标题:10.迭代器与生成器

          本文链接:https://www.haomeiwen.com/subject/bvegnctx.html