python yield学习

yield 在 Python 中被称之为 generator(生成器),yield常用于生成一个迭代器。

列表与迭代器

假设我们要实现一个函数,它需要返回一个斐波那契数列的前n个数,平常我们会写作如下

def fb(max): 
   n, a, b = 0, 0, 1 
   res = [] 
   while n < max: 
       res.append(b) 
       a, b = b, a + b 
       n = n + 1 
   return res

我们可以通过如下方式调用

for n in fb(5): 
    print n 

输出为

1
1
2
3
5

但是假如n十分大,大到fb函数创建一个列表就要耗费掉机器的所有内存时,我们便不能通过上述方法来实现。幸运的是python提供了yield关键字。yield返回的是一个迭代器,我们只需将上述fb函数稍作修改

def fb(max): 
   n, a, b = 0, 0, 1 
   #res = [] 
   while n < max: 
       #res.append(b) 
       yield b 
       a, b = b, a + b 
       n = n + 1 
   #return res

我们依旧可以通过如下方式调用

for n in fb(5): 
    print n 

输出为

1
1
2
3
5
不过此时fb已经变为了一个生成器。带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 生成器,调用 fb(5) 不会执行fb 函数,而是返回一个 iterable 对象。在 for 循环执行时,每次循环都会执行 fb 函数内部的代码,执行到 yield b 时,fb 函数就返回一个迭代值,即b的值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。

send()与next()方法

除了使用for来迭代以外,我们还可以通过调用迭代器的next方法

我们重新创建一个十分简单的函数

#!coding: utf-8
def get_primes():
    yield 5
    yield 6
    yield 7
调用方式如下

a = get_primes()
s = a.next()
print s
s = a.next()
print s
s = a.next()
print s
s = a.next()     #此步会报错,因为已经到达函数尾
print s



 输出结果如下 

5
6
7
Traceback (most recent call last):
  File "test.py", line 19, in <module>
    s = a.next()
StopIteration
send()方法用于向迭代器发送数据,具体请看如下事例

def get_primes():
    m = 1            #无实际意义,仅为演示   
    s = yield 5
    print '1',s
    s = yield 6
    print '2',s
    s = yield 7
    print '3',s

a = get_primes()
s = a.next()          #等价于 a.send(None),由于send方法是将值赋值给yield,而在函数开头并不一定会存在yield
print s               #上一步执行到yield,结束并返回5给s
m = a.send('hello')   #从上一步开始执行,即s = 'hello'(yiled 5),知道碰到下一个yield,并返回其值,为6.
print m
m = a.send('world')
print m
m = a.send('!')       #由于yield 7 后再无yield语句,故此步会报错
print m
输出结果如下
5
1 hello
6
2 world
7
3 !
Traceback (most recent call last):
  File "test.py", line 19, in <module>
    m = a.send('!')
StopIteration
从上列可以看出,send()方法用于向生成器中传递值。

总结

  • generator是用来产生一系列值的
  • yield则像是generator函数的返回结果
  • yield唯一所做的另一件事就是保存一个generator函数的状态
  • generator就是一个特殊类型的迭代器(iterator)
  • 和迭代器相似,我们可以通过使用next()来从generator中获取下一个值
  • 通过隐式地调用next()来忽略一些值
  • 通过send()我们可以向yield传递数据

注意事项

       next()为python2.x的用法,在python3中变为__next__()

参考资料 

       https://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/

       https://www.oschina.net/translate/improve-your-python-yield-and-generators-explained?lang=chs&page=1#

第一次写博客,有什么不足还请大家指正,谢谢~


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值