最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • python中的生成器到底是个啥

    正文概述    2020-10-27   182

    python中的生成器到底是个啥

    生成器,是一个用来创建迭代器的工具。它简单而强大,类似写函数那样进行定义,但是需要返回数据时不是使用return,而是使用yield语句。

    生成器函数

    用yield语句返回数据的“函数”,称为生成器函数。我们把上一节中自定义类LessThan改写成生成器函数

    In [30]: def lessthan(n): 
        ...:     for i in range(n-1, -1, -1): 
        ...:         yield i 
        ...:          
        ...:
    
    In [31]: for i in lessthan(5): 
        ...:     print(i) 
        ...:
    4
    3
    2
    1
    0
    In [32]: lt = lessthan(3)
    
    ## 查看生成器对象的__iter__()和__next__():
    In [33]: lt.__iter__?
    Signature:      lt.__iter__()
    Call signature: lt.__iter__(*args, **kwargs)
    Type:           method-wrapper
    String form:    <method-wrapper '__iter__' of generator object at 0x7fc048cb8ba0>
    Docstring:      Implement iter(self).
    
    In [34]: lt.__next__?
    Signature:      lt.__next__()
    Call signature: lt.__next__(*args, **kwargs)
    Type:           method-wrapper
    String form:    <method-wrapper '__next__' of generator object at 0x7fc048cb8ba0>
    Docstring:      Implement next(self).

    通过生成器改写LessThan类后,代码更加简洁紧凑,因为它自动创建了__iter__()和__next__()方法,通过for循环可以遍历生成器对象。

    接下来我们定义一个生成器对象lt,对这个生成器对象调用next(),每一次调用它都会从上次离开的位置回复执行(也就是记住上次执行语句时的所有数据值)。当生成器生成了所有元素(生成器终结)就会引发StopIteration错误。

    In [53]: lt = lessthan(3)
    
    In [54]: next(lt)
    Out[54]: 2
    
    In [55]: next(lt)
    Out[55]: 1
    
    In [56]: next(lt)
    Out[56]: 0
    
    In [57]: next(lt)
    ---------------------------------------------------
    StopIteration      Traceback (most recent call last)
    <ipython-input-37-00f31299a3f9> in <module>
    ----> 1 next(lt)
    
    StopIteration:

    生成器解析式

    为了实现一些简单的生成器,我们可以不用函数的形式,而是用类似列表解析式的语法,将外层的方括号用圆括号代替即可。

    生成器表达式相比完整的生成器更紧凑但较不灵活,相比等效的列表推导式则更为节省内存。比如下面的的代码,用列表表达式生成的mylist的每个元素都保存在内存中,而mygener每次迭代时才会产生一个元素。假设元素个数不是10,而是100万甚至更多,此时生成器的内存优势会非常明显。

    In [41]: mylist = [i*i for i in range(10)]
    
    In [42]: mylist
    Out[42]: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    
    In [43]: mygener = (i*i for i in range(10))
    
    In [44]: mygener
    Out[44]: <generator object <genexpr> at 0x7fc048be3bf8>

    生成器解析式被设计用于生成器将立即被外层函数所使用的情况,比如:

    In [45]: sum(i*i for i in range(10))
    Out[45]: 285

    sum()括号里面的i*i for i in range(10)就是一个生成器解析式,避免生成一个列表而占用过多内存。

    同样的,下面的例子中都是使用了生成器解析式:

    xvec = [10, 20, 30]
    yvec = [7, 5, 3]
    sum(x*y for x,y in zip(xvec, yvec))         # dot product
    
    from math import pi, sin
    sine_table = {x: sin(x*pi/180) for x in range(0, 91)}
    
    unique_words = set(word  for line in page  for word in line.split())
    
    valedictorian = max((student.gpa, student.name) for student in graduates)
    
    data = 'golf'
    list(data[i] for i in range(len(data)-1, -1, -1))

    总结

    Python提供了两种方式实现生成器:

    (1)生成器函数

    语法上与普通函数相似,用yield替代return换回值;自动实现迭代器协议:__iter__()方法和__next__()方法。没有值可返回时,引起StopInteration异常。yield语句挂起生成器函数的状态,以便再次迭代时从离开的状态继续执行。

    (2)生成器解析式

    类似列表解析式,用圆括号替换方括号,从而简单实现简单的生成器。

    (3)生成器的优点

    代码紧凑,节省内存。不像列表可以多次遍历,生成器只能遍历一遍。


    起源地下载网 » python中的生成器到底是个啥

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元