zoukankan      html  css  js  c++  java
  • 对yield 的理解

      最近在学习Python的时候看到yield的相关语法,感觉很独特,相比其他如C/C++的语法比较有意思,于是在看完资料相关章节做一个总结。

      yield 是一个类似于 return的语法,但是对于return 而言,在其执行之后,意味着将数据返回给调用者,子程序结束,但是yield却不一样,它能够继续执行,直到下一个yield 转交执行权,之后又可以进入继续执行,周而复始,直到抛出异常。

      for in range()是一个简单有用的循环,之前的学习知道range()返回的是一个对象,有惰性求值的特点,下面是一个利用yield简单模拟range()函数的特点

    def xrange(m):
        n=m
        while(n):
            n-=1
            yield n
    for i in xrange(5):
        print(i)

    结果:

    '''
    4
    3
    2
    1
    0
    '''

    这种独特语法现象的原因,从书中摘出相关资料如下:

      当函数中使用yield产生一个值的时候,调用函数会返回一个generator对象,也就是一个生成器,此对象有__next__()方法,通常会调用next()调用该方法取出下一个产生的值,若无法产生下一个值,就会发生StopIteration这样的异常  --《Python程序设计教程》

    除了解释以上现象,反之也可推测 for in 函数的参数可以是生成器,生成器具有惰性求值特点,推测之前遇到过惰性求值的都是生成器(推测)

    yield可以通过send函数来产生值,下面用一个课本上的DEMO来熟悉其相关函数的使用,课本完成了一个生产者消费者模型:

    import random
    def producer():
        while True:
            data=random.randint(0,9)
            print('生产了:',data)
            yield data
    def consumer():
        while True:
            data=yield
            print('消费了:',data)
    def clerk(jobs,producer,consumer):
        print('执行了{}次生产与消费'.format(jobs))
        p=producer()
        c=consumer()
        next(c)           #这里容易出错
        for i in range(jobs):
            data=next(p)
            c.send(data)
    clerk(5,producer,consumer)    

    上面注释的地方比较有意思,只是执行一次yield,而没有任何输出,似乎是没用,但是删除之后程序却无法执行,我的理解是必须执行一次使值转化成生成器对象才能接受相关数据。

    为了印证我的观点,执行以下代码:

    print(type(producer))
    print(type(producer()))

    输出:

    '''
    <class 'function'>
    <class 'generator'>
    
    '''
  • 相关阅读:
    HDU 1850 Being a Good Boy in Spring Festival
    UESTC 1080 空心矩阵
    HDU 2491 Priest John's Busiest Day
    UVALive 6181
    ZOJ 2674 Strange Limit
    UVA 12532 Interval Product
    UESTC 1237 质因子分解
    UESTC 1014 Shot
    xe5 android listbox的 TMetropolisUIListBoxItem
    xe5 android tts(Text To Speech)
  • 原文地址:https://www.cnblogs.com/lumaoxin/p/6931195.html
Copyright © 2011-2022 走看看