zoukankan      html  css  js  c++  java
  • 生成器,生成器表达式。

    今天在看python的时候接触到了生成器和生成器表达式的概念,感觉有点迷糊。特此总结记忆一下。

    生成器的出现可以说是基于下面一种需求。首先,我们来看一端python程序。

    [root@racnode1 tmp]# cat /tmp/test
    aaaaa
    bbbbbbbbb
    ccccc
    ddddd
    [root@racnode1 tmp]# python
    Python 2.6.6 (r266:84292, Dec 20 2012, 15:52:58)
    [GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> f = open('/tmp/test')
    >>> allLineLens=[len(x.strip())  for x in f]
    >>> f.close()
    >>> max(allLineLens)
    9

    首先我们看到一个很简单的文件/tmp/test 共有四行,第二行最长有9个字符。 然后我们用一段python程序来检测该文件最长的行长度是多少。

    f=open('/tmp/test')是打开这个文件。

    allLineLens=[len(x.strip())  for x in f] 是通过一个列表解析来获得一个列表。该列表中的每一个元素都是f中每一行的长度

    f.close()是关闭文件

    max(allLineLens)是找出该列表中最大的值。

    这段程序清晰明了,但是有一个问题,如果这个文件非常大,那么我们要得到的列表可能就会非常大。这样会占用内存很大。这里我们就可以用到生成器表达式来解决这个问题。生成器表达式的语法和列表表达式一样。只是不用[],而且它生成的不是列表而是一个生成器。什么是生成器我们稍后解释。

    列表解析:
    [expr for iter_var in iterable if cond_expr]
    生成器表达式:
    (expr for iter_var in iterable if cond_expr)

    上面的例子用生成器表达式来改写就是:

    >>> f = open('/tmp/test')
    >>> max( len(x.strip()) for x in f)
    9

    这段代码与上面的区别是 len(x.strip()) for x in f返回的不是一个列表而是一个生成器对象。生成器占用内存非常小。所以就解决了我们之前列表占用内存过大的问题。

    那么生成器是什么呢? 

    生成器是一次生成一个值的特殊类型函数。可以将其视为可恢复函数。调用该函数将返回一个可用于生成连续 x 值的生成器【Generator】

    简单的说就是在函数的执行过程中,yield语句会把你需要的值返回给调用生成器的地方,然后退出函数,下一次调用生成器函数的时候又从上次中断的地方开始执行,而生成器内的所有变量参数都会被保存下来供下一次使用。

    1. >>> def fib(max):  
    2.     a, b = 01            
    3.     while a < max:  
    4.         yield a            
    5.         a, b = b, a + b  
    6.   
    7.       
    8. >>> for i in fib(1000):  
    9.     print(i)  
    10.   
    11.       
    12. 0  
    13. 1  
    14. 1  
    15. 2  
    16. 3  
    17. 5  
    18. 8  
    19. 13  
    20. 21  
    21. 34  
    22. 55  
    23. 89  
    24. 144  
    25. 233  
    26. 377  
    27. 610  
    28. 987  
    29.   
    30. >>>f = fib(1000)  
    31. >>>f.next()            #python 3.0 要写成f.__next__()  否则出错  
    32. 0  
    33. >>>f.next()  
    34. 1  
    35. >>>f.next()  
    36. 1  
    37. >>>f.next()  
    38. 2  

    #python 3.0 要写成f.__next__()  否则出错  AttributeError: 'generator' object has no attribute 'next'

    在函数fib(max)内定义了一个生成器,但是对fib(max)的调用永远只能获得一个单独的生成器对象,而不是执行函数里面的语句,这个对象(generator object)包含了函数的原始代码和函数调用的状态,这状态包括函数中变量值以及当前的执行点——函数在yield语句处暂停(suspended),返回当前的值并储存函数的调用状态,当需要下一个条目(item)时,可以再次调用next,从函数上次停止的状态继续执行,知道下一个yield语句。

    生成器和函数的主要区别在于函数 return a value,生成器 yield a value同时标记或记忆 point of the yield 以便于在下次调用时从标记点恢复执行。 yield 使函数转换成生成器,而生成器反过来又返回迭代器。

    有三种方式告诉循环生成器中没有更多的内容:

    1. 执行到函数的末尾("fall off the end")
    2. 用一个return语句(它可能不会返回任何值)
    3. 抛出StopIteration异常

    总的来说生成器是一类特殊 迭代器。 一个产生值的函数 yield 是一种产生一个迭代器却不需要构建迭代器的精密小巧的方法

  • 相关阅读:
    Linux makefile讲解
    Linux问题集锦
    Linux 用户和组管理
    鸟哥的Linux私房菜——第八章
    考驾照的波折~
    Expression Blend实例中文教程(1)
    Silverlight & Blend动画设计系列十三:三角函数(Trigonometry)动画之飘落的雪花(Falling Snow)
    Silverlight & Blend动画设计系列十二:三角函数(Trigonometry)动画之自由旋转(Free-form rotation)
    Silverlight & Blend动画设计系列十一:沿路径动画(Animation Along a Path)
    Silverlight & Blend动画设计系列十:Silverlight中的坐标系统(Coordinate System)与向量(Vector)运动
  • 原文地址:https://www.cnblogs.com/kramer/p/3544591.html
Copyright © 2011-2022 走看看