zoukankan      html  css  js  c++  java
  • Python 生成器和迭代器

    1. 生成器

    • 通过列表生成式,可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个
      包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数
      的元素占用的空间都白白浪费了。所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的
      过程中不断推算出后续的元素呢?这样,就不必创建完整的list,从而节省大量的空间。
    • 在Python中,这种一边循环一边计算的机制,称为生成器(generator)
    # 列表生成式,值一下子,全部计算出来:
    L = [ x*2 for x in range(5)]
    L   # 输出: [0, 2, 4, 6, 8]
    
    # 创建生成器, 列表元素是推算出来的:
    G = ( x*2 for x in range(5))
    G   # 输出: <generator object <genexpr> at 0x1077d9db0>
    next(G) # 每执行一次 next(),输出一个元素, 等价于 G.__next__(), Python 2.x : G.next()
    
    
    # 创建生成器的第二种方式: 使用函数(yield 关键字)
    # 斐波拉契数列(Fibonacci)
    def fib(times):
        n = 0
        a, b = 0, 1
        while n < times:
            print(b)
            a, b = b, a+b
            n += 1
        return 'done'
    
    fib(5)
    
    
    # 生成器(ipython 中操作)
    def fib():
        print("=== start ===")
        a, b = 0, 1
        for i in range(5):
            print("=== 1 ===")
            yield b
            print("=== 2 ===")
            a, b = b, a+b
            print("=== 3 ===")
        print("=== stop ===")
    
    a = fib()
    a   # 输出: <generator object fib at 0x23355>
    next(a)   # 等价于 a.__next__()
    # 输出:
    # === start ===
    # === 1 ===
    #   1
    
    # 此时,fib()函数就是生成器,可以使用循环来迭代
    for num in a:
        print(num)
    

    1.1 send 方法

    # 示例:
    # ipython3 中操作
    def gen():
        i = 0
        while i<5:
            temp = yield i
            print(temp)
            i+=1
    
    a = gen()
    
    a.__next__()    # 输出: 0
    a.__next__()    # 输出: None
    c = a.send("haha")  # 输出: haha
    print(c)        # 输出: 2
    
    # 说明: 程序执行到yield时,gen函数暂时停止,同时返回i的值;
    # temp 接收send过来的值(haha);
    # a.__next__() 等价 a.send(None)
    # 若是第一次直接调用 a.send("haha"), 程序会报错
    

    2. 迭代器

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

    2.1 可迭代对象

    • 可以直接作用于 for 循环的数据类型有以下几种:
      • 集合数据类型:list, tuple, dict, set, str等;
      • generator, 包括生成器和带 yieldgeneration function;
      • 这些可以直接作用于for循环的对象统称为可迭代对象(Iterable)
    • 可以使用 isinstance() 判断一个对象是否是 Iterable对象;
    • 拥有内置方法 __iter__() ;
    # 示例:
    from collections import Iterable
    isinstance([], Iterable)    # True
    

    2.2 迭代器

    • 可以被 next() 函数调用并不断返回下一个值的对象称为迭代器(Iterator);
    • 可以使用 isinstance() 判断一个对象是否是 Iterator 对象;
    # 示例:
    from collections import Iterator
    isinstance((x for x in range(10), Iterator)  # True
    isinstance([], Iterator)  # False
    

    2.3 iter()函数

    • 生成器都是 Iterator 对象;
    • list, dict, str虽然是 Iterable,却不是 Iterator;
    • 可以使用 iter() 函数把 list,dict, str等 Iterable 变成 Iterator;
    # 示例:
    from collections import Iterator
    isinstance(iter([]), Iterator)  # True
    

    参考资料:

  • 相关阅读:
    Linux 部署 nginx
    Linux 部署vue项目(使用nginx)
    git 操作规范
    mysql grant权限分配(转)。
    前端优化,包括css,jss,img,cookie
    关于js里的那一堆事件
    个人作业——软件工程实践总结作业
    Unity3D 快捷键
    Beta冲刺第二天
    Beta冲刺第一天
  • 原文地址:https://www.cnblogs.com/linkworld/p/8542887.html
Copyright © 2011-2022 走看看