zoukankan      html  css  js  c++  java
  • python生成器

      通过列表生成式,我们可以直接创建一个列表,但是收到内存限制,列表容量是有限的。而且创建一个包含100万个元素的列表未免太占用空间了,如果我们只需要访问前面的几个元素,那多出来的空间就被白白浪费掉了。所以如何只生成前几个元素呢?

      所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。

      要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

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

      我们可以通过下标打印出,list的每个元素,那么怎么打印生成器对应的元素呢?

      如果要一个一个打印,可以使用next()方法。next(g)

      不过我们一般使用for循环:

      

      生成器的两种形式(Python有两种不同的方式提供生成器)  

      1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。生成器和函数的执行流程不一样,函数是顺序执行,遇到return语句或者最后一行函数语句就结束。在调用生成器运行过程中,每次遇到yield时函数会暂停并保存当前所有的运行信息,返回yield值。并在下一次执行next方法时,从当前位置继续运行。

      yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator。

      下面为一个可以无穷生产奇数的生成器函数。(可以看出使用生成器是十分方便的)

      

    def odd():
        n=1
        while True:
            yield n
            n+=2
    odd_num = odd()
    count = 0
    for o in odd_num:
        if count >=5: break
        print(o)
        count +=1

      

      2、生成器表达式:类似于列表推导,但,生成器返回按需生产结果的一个对象,而不是一次构建一个结果列表。

      

    g = (i for i in range(10**100))#生成器表达式
    L = [i for i in range(10**100)]#列表生成式

      一个小例子

      斐波那契数列的实现,虽然它无法使用列表推导式打印出来,但是用函数可以轻易的打印出来

      

    1 def fib(max):
    2     n, a, b = 0, 0, 1
    3     while n < max:
    4         print b
    5         a, b = b, a + b
    6         n = n + 1

      怎么能用生成器的方法来实现呢?只需把return改成yield就好。

      

     def fib(max):
         n, a, b = 0, 0, 1
         while n < max:
             yield b
             a, b = b, a + b
             n = n + 1
     In [67]: fib(6)
     Out[67]: <generator object fib at 0x000000000484BD58>
     
     In [68]: a = fib(6)
     
     In [69]: next(a)
     Out[69]: 1
     
     In [70]: next(a)
      Out[70]: 1
     
      In [71]:

      当我们调用fib(6)的时候,提示这是一个generator对象。是不能这么打印的。

      

  • 相关阅读:
    C++类中使用new及delete小例子(续)
    C++类中使用new及delete小例子
    C++类中static修饰的函数的使用
    C++类使用static小例子(新手学习C++)
    C++结构体中使用函数与类中使用函数小结
    记一次简单的性能优化
    [转载]Java的内存回收机制
    写给自己的项目总结
    [转载]正则表达式30分钟入门教程
    使用JRockit进行性能优化一:环境搭建
  • 原文地址:https://www.cnblogs.com/happyfool/p/8576018.html
Copyright © 2011-2022 走看看