生成器

基于yield指令,可以暂停一个函数并返回中间结果。该函数将保存执行环境并且可以在必要
时恢复。

>>> def fibonacci():
... a, b = 0, 1
... while True:
... yield b
... a, b = b, a + b
...
>>> fib = fibonacci()
>>> fib.next()
1
>>> fib.next()
1
>>> fib.next()
2
>>> [fib.next() for i in range(10)]
[3, 5, 8, 13, 21, 34, 55, 89, 144, 233]
>>>

该函数将返回一个特殊的迭代器,也就是generator对象,它知道如何保存执行环境。对它的
调用是不确定的,每次都将产生序列中的下一个元素。

生成器对降低程序复杂性很有帮助:

>>> def power(values):
... for value in values:
... print 'powering %s' % value
... yield value
...
>>> def adder(values):
... for value in values:
... print 'adding to %s' % value
... if value % 2 == 0:
... yield value + 3
... else:
... yield value + 2
...
>>> elements = [1, 4, 7, 9, 12, 19]
>>> res = adder(power(elements))
>>> res.next()
powering 1
adding to 1
3
>>> res.next()
powering 4
adding to 4
7


Python引入的与生成器相关的最后一个特性是提供了与next方法调用的代码进行交互的
功能。yield将变成一个表达式,而一个值可以通过名为send的新方法来传递:

>>> def psychologist():
... print 'Please tell me your problems'
... while True:
... answer = (yield)
... if answer is not None:
... if answer.endswith('?'):
... print ("Don't ask yourself too much questions")
... elif 'good' in answer:
... print "A that's good, go on"
... elif 'bad' in answer:
... print "Don't be so negative"
...
>>> free = psychologist()
>>> free.next()
Please tell me your problems
>>> free.send('I feel bad')
Don't be so negative
>>> free.send("Why i shouldn't ?")
Don't ask yourself too much questions

send的工作机制与next一样,但是yield将变成能够返回传入的值。因为,这个函数可以
根据客户端代码来改变其行为。同时,还添加了throw和close两个函数,以完成该行为。
它们将向生成器抛出一个错误:
throw允许客户端代码传入要抛出的任何类型的异常;
close的工作方式是相同的,但是将会抛出一个特定的异常----GeneratorExit,在
这种情况下,生成器函数必须再次抛出GeneratorExit或StopIteration异
常。

>>> def my_generator():
... try:
... yield 'something'
... except ValueError:
... yield 'dealing with the exception'
... finally:
... print "ok let's clean"
...
>>> gen = my_generator()
>>> gen.next()
'something'
>>> gen.throw(ValueError('mean mean mean'))
'dealing with the exception'
>>> gen.close()
ok let's clean
>>> gen.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration


生成器表达式:

>>> iter = (x**2 for x in range(10) if x % 2 == 0)
>>> for e1 in iter:
... print e1
...
0
4
16
36
64
>>> iter.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration


>>> iter = (x**2 for x in range(10) if x % 2 == 0)
>>> iter.next()
0
>>> iter.next()
4

这种表达式常被称为生成器表达式或genexp。每当在yield表达式上创建简单的循环时,
都应该使用它,或者用它来代替表现类似迭代器的列表推导。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值