美文网首页
python生成器(generator)

python生成器(generator)

作者: Pello_Luo | 来源:发表于2017-11-11 10:58 被阅读0次

    1.生成器(generator)概念

    生成器是迭代器,生成器提供了非常方便的自定义迭代器的途径,在Python中,这种一边循环一边计算的机制,称为生成器(Generator)

    2.生成器作用

    通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间.

    比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
    1, 1, 2, 3, 5, 8, 13, 21, 34, ...

    斐波拉契常规函数写法:
    In [18]: def fib(num):
        ...:     a,b,n=0,1,0
        ...:     while n<num:
        ...:         print(b)
        ...:         a,b=b,a+b
        ...:         n+=1
        ...:
    
    In [19]: fib(5)
    1
    1
    2
    3
    5
    

    3.生成器创建

    常见的生成器创建有两种形式:
    ①生成器表达式
    ②生成器函数

    3.1.生成器表达式

    生成器表达式与列表解析式极为相似,将列表解析式'[]'改成'()'就是一个生成器,生成器拥有next方法并且行为与迭代器完全相同,这意味着生成器也可以用于Python的for循环遍历,看

    In [16]: gen=(x*x for x in range(4))
    In [17]: gen
    Out[17]: <generator object <genexpr> at 0x00000000045335E8> #结果表明为生成器
    In [18]: for i in gen :
                    print(i),
      
    #执行结果
    0 1 4 9
    
    3.1.生成器函数

    生成器函数与普通函数极为相似,若函数中包含了至少一个yield关键字则为生成器,通过生成器函数可实现复杂逻辑的generator,例:

    #定义一个生成器
    In [1]: def gen():
          print('start')
          for  i  in  range(5):
                yield i               #带yield关键字
                print(i)
          print('end')
    ------------------------------------------------------------------------------
    In [2]: gen()
    Out[2]: <generator object gen at 0x0000000004533C18>   #结果表明为生成器
    In [3]: t=gen()
    In [4]: next(t)                 #每次进行迭代时返回一个值
    start
    Out[4]: 0
    In [5]: next(t)
    0
    Out[5]: 1
    In [6]: next(t)
    1
    Out[6]: 2
    In [7]: next(t)
    2
    Out[7]: 3
    In [8]: next(t)
    3
    Out[8]: 4
    In [9]: next(t)
    4
    end
    --------------------- 执行到末尾,迭代器遇到StopIteration异常结束
    StopIteration                             Traceback (most recent call last)
    <ipython-input-9-9494367a8bed> in <module>()
    ----> 1 next(t)
    StopIteration:
    

    4.生成器函数执行过程

    生成器函数中的yield关键字包含两种功能:

    1.返回
    2.挂起

    [L1] def gen():
    [L2]      print('start')
    [L3]      for  i  in  range(5):
    [L4]            yield i              
    [L5]            print(i)
    [L6]      print('end')
    

    1.第一次执行next(generator)时,会执行完yield语句后程序进行挂起,所有的参数和状态会进行保存
    2.再一次执行next(generator)时,会从挂起的状态开始往后执行。
    在遇到程序的结尾或者遇到StopIteration时,循环结束

    yield 与 return

    5.生成器自带方法属性

    #在ipython中对之前创建的gen生成器对象查看帮助
    In [20]: help(gen)
    Help on generator object:
    <genexpr> = class generator(object)
     |  Methods defined here:
     |
     |  __getattribute__(...)
     |      x.__getattribute__('name') <==> x.name
     |
     |  __iter__(...)
     |      x.__iter__() <==> iter(x)
     |
     |  __repr__(...)
     |      x.__repr__() <==> repr(x)
     |
     |  close(...)
     |      close() -> raise GeneratorExit inside generator.
     |
     |  next(...)
     |      x.next() -> the next value, or raise StopIteration
     |
     |  send(...)
     |      send(arg) -> send 'arg' into generator,
     |      return next yielded value or raise StopIteration.
     |
     |  throw(...)
     |      throw(typ[,val[,tb]]) -> raise exception in generator,
     |      return next yielded value or raise StopIteration.
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors defined here:
     |
     |  gi_code
     |
     |  gi_frame
     |
     |  gi_running
    

    通过上面的帮助文件可以归纳出生成器的方法有

    1.close()
    手动关闭生成器函数,后面的调用会直接返回StopIteration异常。
    2.send()
    生成器函数最大的特点是可以接受外部传入的一个变量,并根据变量内容计算结果后返回
    3.throw()
    用来向生成器函数送入一个异常,可以结束系统定义的异常,或者自定义的异常。
    throw()后直接跑出异常并结束程序,或者消耗掉一个yield,或者在没有下一个yield的时候直接进行到程序的结尾。

    6.yield from

    相关文章

      网友评论

          本文标题:python生成器(generator)

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