zoukankan      html  css  js  c++  java
  • Python的生成器Generator小结

    一. 生成器的介绍

    在介绍生成器(Generator)之前,我们首先需要熟悉列表生成式,列表生成式是Python内置的简单又强大的用来创建列表的生成式。

    举个例子,

    如果我们想生成[1*1,2*2,3*3,4*4,5*5,6*6,7*7,8*8,9*9]

    比较笨的方法是

    l = []
    for i in range(1,10):
        l.append(i*i)

    而列表生成式可以用一句语句代替上述的循环语句:

    [i*i for i in range(1,10)]

    更方便的是我们可以添加条件判断,或者使用多层循环,达成我们想要的结果:

    #用if判断来获取偶数的平方
    [ i*i for i in range(1,10) if i%2==0 ]
    
    #二重循环实现排列组合
    [ x + y for x in 'abc' for y in '123' ]

    言归正传,回到生成器。生成器典型的应用场景是这样的: 假如我们需要生成100万个元素,但是我们需要用到的往往只有几个怎么办?如果用列表生成式全部创建的话,则会浪费大量的空间: 为了需要用到的几个元素,我们创建了100万个元素的列表。

    而生成器正是这样可以不必创建完成列表,可以一边循环一边计算出后续元素的机制。

    创建生成器的方法很简单,只需要把创建列表生成式时的'[]'改成'()'即可

    #List
    l = [ i*i for i in range(1,10) if i%2==0 ]
    
    #Generator
    g = ( i*i for i in range(1,10) if i%2==0 )

    生成器的用法:通过next()函数获得下一个生成的值。直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

    >>> next(g)
    4
    >>> next(g)
    16
    >>> next(g)
    36
    >>> next(g)
    64
    >>> next(g)
    Traceback (most recent call last):
      File "<pyshell#73>", line 1, in <module>
        next(g)
    StopIteration

    更科学的方法是使用for循环,因为generator也是可迭代对象,并且不需要关心StopIteration的错误。

    >>> for i in g:
        print(i)
    
        
    4
    16
    36
    64

    当我们的生成器的需要计算的比较复杂,无法通过类似列表生成式的for循环实现时,则需要另外一种实现生成器的方法:在函数中使用'yield'关键字

    def fib(max):
        n, a, b = 0, 0, 1
        while n < max:
            yield b
            a, b = b, a + b
            n = n + 1
        return 'Done'

    对上述代码有以下几点:

    1. 代码的作用是用生成器的方法实现斐波那契数列

    2. 函数中使用关键字''yield"之后,函数就不再是普通的函数了,而变成了生成器

    3. generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

    4. 生成器中可以没有return语句,并不影响生成器的功能。上述代码例子中带的return 'Done',将会在抛出StopIteration的错误时打印出来。你可以用next()函数触发StopIteration错误试一试。

    二. 迭代器和可迭代对象

    迭代器:迭代器就是Iterator,意思指可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值。毫无疑问,我们的生成器就属于迭代器(Iterator)。

    可迭代对象:Iterable Object,可以直接作用于for循环的对象统称为可迭代对象Iterable Object。显然,生成器也属于可迭代对象。list, tuple, dict, set, str因为可以直接作用于for循环,所以也是可迭代对象;但是无法被next()函数调用返回下一个值,所以不属于迭代器。

    总结: 生成器Generator即是迭代器(Iterator),也是可迭代对象(Iterable Object)。其实从定义上分析,迭代器一定是可迭代对象。

    list, tuple, dict, set, str是可迭代对象(Iterable Object),但不是迭代器(Iterator)。

  • 相关阅读:
    什么是重构,什么不是重构
    Sql Server Merge 关键字 一个条语句实现增删改查
    SQLServer查询一天时间内的数据
    数据库索引原理 二
    重构代码时的7个阶段
    “旁观者效应”是如何毁掉我们的代码
    ClassNotFoundException: org.apache.storm.kafka.spout.KafkaSpoutConfig
    Flume+Kafka整合使用
    SLF4J: Detected both log4joverslf4j.jar AND bound slf4jlog4j12.jar on the class path
    Could not find or load main class org.apache.flume.tools.GetJavaProperty
  • 原文地址:https://www.cnblogs.com/ArsenalfanInECNU/p/9605171.html
Copyright © 2011-2022 走看看