zoukankan      html  css  js  c++  java
  • python yield生成器 分类: python基础学习 2013-08-04 15:40 324人阅读 评论(0) 收藏

    yield:生成器

    任何使用yield的函数都称之为生成器,如:

    Python代码  收藏代码
    1. def count(n):  
    2.     while n > 0:  
    3.         yield n   #生成值:n  
    4.         n -= 1  

     

    另外一种说法:生成器就是一个返回迭代器的函数,与普通函数的区别是生成器包含yield语句,更简单点理解生成器就是一个迭代器。

    使用yield,可以让函数生成一个序列,该函数返回的对象类型是"generator",通过该对象连续调用next()方法返回序列值。

    Python代码  收藏代码
    1. c = count(5)  
    2. c.next()  
    3. >>> 5  
    4. c.next()  
    5. >>>4  

     

    生成器函数只有在调用next()方法的时候才开始执行函数里面的语句,比如:

    Python代码  收藏代码
    1. def count(n):  
    2.     print "cunting"  
    3.     while n > 0:  
    4.         yield n   #生成值:n  
    5.         n -= 1  

     

    在调用count函数时:c=count(5),并不会打印"counting"只有等到调用c.next()时才真正执行里面的语句。每次调用next()方法时,count函数会运行到语句yield n处为止,next()的返回值就是生成值n,再次调用next()方法时,函数继续执行yield之后的语句(熟悉Java的朋友肯定知道Thread.yield()方法,作用是暂停当前线程的运行,让其他线程执行),如:

    Python代码  收藏代码
    1. def count(n):  
    2.     print "cunting"  
    3.     while n > 0:  
    4.         print 'before yield'  
    5.         yield n   #生成值:n  
    6.         n -= 1  
    7.         print 'after yield'  

     

    上述代码在第一次调用next方法时,并不会打印"after yield"。如果一直调用next方法,当执行到没有可迭代的值后,程序就会报错:

    Traceback (most recent call last): File "", line 1, in StopIteration

    所以一般不会手动的调用next方法,而使用for循环:

    Python代码  收藏代码
    1. for i in count(5):  
    2.     print i,  

     

    实例: 用yield生成器模拟Linux中命令:tail -f | grep python 用于查找监控日志文件中出现有python字样的行。

    Python代码  收藏代码
    1. import time  
    2. def tail(f):  
    3.     f.seek(0,2)#移动到文件EOF,参考:[seek](http://docs.python.org/2/library/stdtypes.html?highlight=file#file.seek)  
    4.     while True:  
    5.         line = f.readline()  #读取文件中新的文本行  
    6.         if not line:  
    7.             time.sleep(0.1)  
    8.             continue  
    9.         yield line  
    10.   
    11. def grep(lines,searchtext):  
    12.     for line in lines:  
    13.         if searchtext in line:  
    14.             yield line  

     

    调用:

    Python代码  收藏代码
    1. flog = tail(open('warn.log'))  
    2. pylines = grep(flog,'python')  
    3. for line in pylines:  
    4.     print line,  

     

    用yield实现斐波那契数列:

    Python代码  收藏代码
    1. def fibonacci():  
    2.     a=b=1  
    3.     yield a  
    4.     yield b  
    5.     while True:  
    6.         a,b = b,a+b  
    7.         yield b  

     

    调用:

    Python代码  收藏代码
    1. for num in fibonacci():  
    2.     if num > 100:  
    3.         break  
    4.     print num,  

     

    yield中return的作用:
    作为生成器,因为每次迭代就会返回一个值,所以不能显示的在生成器函数中return 某个值,包括None值也不行,否则会抛出“SyntaxError”的异常,但是在函数中可以出现单独的return,表示结束该语句。
    通过固定长度的缓冲区不断读文件,防止一次性读取出现内存溢出的例子:

    Python代码  收藏代码
    1. def read_file(path):  
    2.     size = 1024  
    3.     with open(path,'r') as f:  
    4.         while True:  
    5.             block = f.read(SIZE)  
    6.             if block:  
    7.                 yield block  
    8.             else:  
    9.                 return  

     

    如果是在函数中return 具体某个值,就直接抛异常了

    Python代码  收藏代码
    1. >>> def test_return():  
    2. ...      yield 4  
    3. ...      return 0  
    4. ...  
    5.   File "<stdin>", line 3  
    6. SyntaxError: 'return' with argument inside generator  

     

    与yield有关的一个很重要的概念叫**协程**,下次好好研究研究。

    参考:
    http://www.cnblogs.com/huxi/archive/2011/07/14/2106863.html
    http://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/
    《Python 参考手册》

  • 相关阅读:
    -bash: fork: Cannot allocate memory 问题的处理
    Docker top 命令
    docker常见问题修复方法
    The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
    What's the difference between encoding and charset?
    hexcode of é î Latin-1 Supplement
    炉石Advanced rulebook
    炉石bug反馈
    Sidecar pattern
    SQL JOIN
  • 原文地址:https://www.cnblogs.com/think1988/p/4628113.html
Copyright © 2011-2022 走看看