python进阶学习之 yield

背景介绍    

 最近在学习Tornado的async编程技巧, 发现yield是基础, 为了弥补之前对他的疏忽, 特此发文深入加深其印象, 以及提高其作用。

基础概念

        yield的作用就是挂起程序, 并且返回yield之后的值。 举个很简单的例子:

​
#-*- coding: utf-8 -*-

def gen():
    b = yield "yield value"
    print "StateA ", b

generator = gen()
print generator.next()

​

        对上述程序进行简单的分析:

  • 执行输出的结果:yield value, 
  • generator = gen() , 创建一个生成器, (含有yield的函数体, 其函数调用的结果就是生成一个生成器, 不会执行其函数体。)
  • generator.next(),   只有当生成器的next函数被第一次触发, 函数体才会被执行, 到第一个yield处挂起。程序稍作修改来验证一下:
#-*- coding: utf-8 -*-

def gen():
    print "enter gen()"
    b = (yield "yield value")#pause
    print "StateA ", b

generator = gen()
print "created a generator"
print generator.next()

执行结果:

created a generator
enter gen()
yield value

  • 如果生成器的next函数被第二次触发(再次例子中), 由于没有yield了, 会在函数体执行结束之后抛出异常。  
#-*- coding: utf-8 -*-

def gen():
    b = (yield "yield value")#pause
    print "StateA ", b

generator = gen()
print generator.next()
print generator.next()

执行结果:

yield value
StateA  None
Traceback (most recent call last):
  File "yield-sample.py", line 9, in <module>
    print generator.next()
StopIteration

  • b = (yield "yield value") ,  从上述的执行结果中看, b的值为None, 同时应该注意到, 复制动作是在第二次next的时候被调用到的。
  • 我们再想, 如何让yield expression有返回值,  并且此返回值是从外围穿入进去的, 这正是generator.send(value)要做的事情:
#-*- coding: utf-8 -*-

def gen():
    b = (yield "yield value")#pause
    print "StateA ", b

generator = gen()
print generator.next()
print generator.send("yield expression return value")

执行结果

yield value
StateA  yield expression return value
Traceback (most recent call last):
  File "yield-sample.py", line 9, in <module>
    print generator.send("yield expression return value")
StopIteration

  •  下面的代码是不是也是可以的?

#-*- coding: utf-8 -*-

def gen():
    b = (yield "yield value")#pause
    print "StateA ", b

generator = gen()
print generator.send("yield expression return value")

    其实没啥, 就是去掉了 print generator.send(None)

执行结果

Traceback (most recent call last):
  File "yield-sample.py", line 8, in <module>
    print generator.send("yield expression return value")
TypeError: can't send non-None value to a just-started generator

这是为什么? 这要追述一下generator.send(value)的作用: 给yield表达式传值, 也就是说让(yield expression) = value,  (注意: 是刚刚挂起的yield); 为了达到这个目的, 在此之前一定要让generator挂起一次才行, 所以在此之前必须有generator.next()/send(None) 的调用。

总结

带有yield表达式的函数在运行的时候就是一个generator(生成器), 此生成器有两个对外的函数, next()和send(value)

  • 相同点

generator.send(None) 和generator.next() 作用是相同的。 都是驱使生成器从一个yield向下一个yield去执行函数体, 然后挂起返回yield后面的表达式。

  • 不同点

1.   generator.send(value)  要在generator.next()/send(None)之后执行,  他的作用: 返回当前挂起yield expression = value, 如果让当前的yield挂起, 必须执行一次next()/send(None)。

2.  其实最大的不同就是, send可以把函数外的value能传到到函数中, 而next不能。

 

转载于:https://my.oschina.net/u/929394/blog/687311

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值