zoukankan      html  css  js  c++  java
  • Python列表生成器

    本篇将介绍python生成器,更多内容请参考:python学习指南

    前言

    通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅访问前面几个元素,那后面绝大多数占用的空间都白白浪费了。
    python生成器是用来代替"不一定能够使用全部元素的数组",等到使用某一元素时,才生成该元素,用来节省空间.

    生成器创建方式

    第一种:

    在前面我们介绍python列表生成式,这里我们只需要把列表生成式的[]改成(),就创建了一个generatro

    >>>L = [x * x for x in range(10)]
    >>>L
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
    >>>g = (x*x for x in range(10))
    >>>g
    <generator object <genexpr> at 0x1022ef630>
    

    创建Lg的区别仅在于最外层的[](),L是一个list,而g是一个generator
    上面表达式中我们可以直接列出list(L)的每一个元素,但我们打印g的时候,却打印了g的类型,那么,我们如何打印generator的每一个元素呢?
    如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:

    >>>next(g)
    0
    >>>next(g)
    1
    >>>next(g)
    4
    >>>next(g)
    9
    >>>next(g)
    16
    >>>next(g)
    25
    >>>next(g)
    36
    >>>next(g)
    49
    >>>next(g)
    64
    >>>next(g)
    81
    >>>next(g)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
    

    generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,知道计算出最后一个元素,没有更多元素时,抛出StopIteration的错误。
    这样不断调用next(g)实在是太变态了,生成器是可迭代对象

    >>>from collections import Iterable  #载入模块
    >>>isinstance(g, Iterable)  #生成器是可迭代对象吗?
    True
    

    这样,知道用什么来了吧?
    当然是使用强大的for...in迭代来实现

    >>>g = (x * x for x in range(10))
    >>>for n in g:
        print(n)
    0
    1
    4
    9
    16
    25
    36
    49
    64
    81
    

    通过for迭代的方式来循环生成器,并不用关心StopIteration的错误。

    使用关键字 yield 关键字

    generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现

    斐波那契数列生成器

    def creatNum():
        print("---开始执行生成器方法---")
        a,b = 0,1
        for i in range(0,5):
            print("--step1--")
            yield b
            print("--step2--")
            a,b = b,a+b
            print("--step3--")
        print("--stop--")
    
    print("直接调用方法...")
    print(creatNum())
    
    #这里用一个标识符来指向生成器(不要把creatNum()当做函数)
    func = creatNum()
    
    #使用for循环来执行生成器
    for i in func:
        print(i)
    输出结果: (执行完毕不会崩溃)
    
    #直接调用方法...
    <generator object creatNum at 0x101c30f10>
    ---开始执行生成器方法---
    --step1--
    1
    --step2--
    --step3--
    --step1--
    1
    --step2--
    --step3--
    --step1--
    2
    --step2--
    --step3--
    --step1--
    3
    --step2--
    --step3--
    --step1--
    5
    --step2--
    --step3--
    --stop--
    

    在执行生成器时,可以使用 生成器.send(param) 方法
    send方法不光是执行一步next操作,还会把send里面的参数传到生成器中充当yield表达式的返回值

    def test():
        i = 0
        while i < 5:
            temp = yield i
            print(temp)
            i += 1
    
    t = test()
    
    #先使用next执行,看能出来什么结果
    t.__next__()
    t.__next__()
    print(t.__next__())
    
    #使用send执行
    t.send("1231231231223123")
    print(t.send("hahahahhahaha"))
    输出结果: (可见next输出temp为none , 而send 则把值传递进了生成器)
    
    None
    None
    2
    1231231231223123
    hahahahhahaha
    4
    

    参考

    1. python生成器是怎样工作的
    2. Python中的yield关键字
    3. python生成器
    4. 廖雪峰-生成器
  • 相关阅读:
    AGC022E Median Replace
    洛谷3195 [HNOI2008]玩具装箱TOY(斜率优化+dp)
    hdu3507 斜率优化学习笔记(斜率优化+dp)
    洛谷3176 [HAOI2015]数字串拆分 (矩阵乘法+dp)
    洛谷5038 [SCOI2012]奇怪的游戏(二分+网络流+判断奇偶)
    洛谷2543AHOI2005]航线规划 (树剖+线段树+割边思路)
    洛谷3973 TJOI2015线性代数(最小割+思维)
    CF911G Mass Change Queries(线段树+暴力)
    洛谷2151[SDOI2009]HH去散步(dp+矩阵乘法优化)
    CF1092F Tree with Maximum Cost(dfs+dp)
  • 原文地址:https://www.cnblogs.com/miqi1992/p/8302597.html
Copyright © 2011-2022 走看看