[python]yield用法浅析

创建生成器(generator)有两种方法:

  • 将list comprehension中的方括号[]变成圆括号()
>>> a=(i for i in range(10))
>>> a
<generator object <genexpr> at 0x02C0A9B8>
  • 在函数中使用yield,该函数自动变成一个生成器
>>> def gen():
	print 'generator'
	yield 0
	print 'step1'
	yield 1
	print 'step2'
	yield 2
	print 'Bye!'

	
>>> g=gen()
>>> g
<generator object gen at 0x02C0A788>

生成器的工作原理是,在执行生成器的时候(其实就是执行函数内的代码),遇到yield就立马停止,并返回yield后面的数据,直到yield下一行没有代码,此时抛出“StopIteration”异常,生成器停止工作。以上面定义的gen()为例进行说明。

>>> g=gen()   # 得到生成器g
>>> g
<generator object gen at 0x02C0A788>
>>> g.next()  # 执行生成器直到遇到yield
generator
0
>>> g.next()  # 从上次执行yield命令的下一行继续执行,直到遇到下一个yield
step1
1
>>> g.next()
step2
2
>>> g.next()  # yield后面没有内容,抛出'StopIteration'异常
Bye!

Traceback (most recent call last):
  File "<pyshell#145>", line 1, in <module>
    g.next()
StopIteration

如果将生成器放到for...in...中——for value in generator,则无需人工调用next()方法,当generator(函数执行过程中)遇到yield的时候,会将yield后面的数据返回给for中的value,然后程序会自动执行next()。如果遇到下一个yield,则重复前面的过程;如果程序执行完毕,则退出for循环。

>>> g=gen()
>>> g
<generator object gen at 0x02C0A788>
>>> for i in g:   # 每次将yield后面的数据返回给i
	print '<value^2={}>'.format(i*i)

	
generator
<value^2=0>
step1
<value^2=1>
step2
<value^2=4>
Bye!

举例,下面的例子展示了输出长度为9的链表,链表中的内容是[0],[0,1],[0,1,2],...[0,1,2,...,8]。使用生成器可以不用将所有待打印的数据保存下来,每次执行过程中才生成相应的序列,然后打出输出。节省了内存空间。

>>> def gen(n):
	a=range(n)
	for i in a:
		yield i

		
>>> l=[]
>>> for i in range(1,10):
	l.append(gen(i))

	
>>> l
[<generator object gen at 0x02C4D2D8>, <generator object gen at 0x02C4E440>, <generator object gen at 0x02C4E148>, <generator object gen at 0x02C4E7D8>, <generator object gen at 0x02C4E670>, <generator object gen at 0x02C4EA80>, <generator object gen at 0x02C4E9E0>, <generator object gen at 0x02C4EC60>, <generator object gen at 0x02C4ED00>]
>>> for i in l:
	for j in i:
		print '[{}]value={}'.format(i,j)

		
[<generator object gen at 0x02C4D2D8>]value=0
[<generator object gen at 0x02C4E440>]value=0
[<generator object gen at 0x02C4E440>]value=1
[<generator object gen at 0x02C4E148>]value=0
[<generator object gen at 0x02C4E148>]value=1
[<generator object gen at 0x02C4E148>]value=2
[<generator object gen at 0x02C4E7D8>]value=0
[<generator object gen at 0x02C4E7D8>]value=1
[<generator object gen at 0x02C4E7D8>]value=2
[<generator object gen at 0x02C4E7D8>]value=3
[<generator object gen at 0x02C4E670>]value=0
[<generator object gen at 0x02C4E670>]value=1
[<generator object gen at 0x02C4E670>]value=2
[<generator object gen at 0x02C4E670>]value=3
[<generator object gen at 0x02C4E670>]value=4
[<generator object gen at 0x02C4EA80>]value=0
[<generator object gen at 0x02C4EA80>]value=1
[<generator object gen at 0x02C4EA80>]value=2
[<generator object gen at 0x02C4EA80>]value=3
[<generator object gen at 0x02C4EA80>]value=4
[<generator object gen at 0x02C4EA80>]value=5
[<generator object gen at 0x02C4E9E0>]value=0
[<generator object gen at 0x02C4E9E0>]value=1
[<generator object gen at 0x02C4E9E0>]value=2
[<generator object gen at 0x02C4E9E0>]value=3
[<generator object gen at 0x02C4E9E0>]value=4
[<generator object gen at 0x02C4E9E0>]value=5
[<generator object gen at 0x02C4E9E0>]value=6
[<generator object gen at 0x02C4EC60>]value=0
[<generator object gen at 0x02C4EC60>]value=1
[<generator object gen at 0x02C4EC60>]value=2
[<generator object gen at 0x02C4EC60>]value=3
[<generator object gen at 0x02C4EC60>]value=4
[<generator object gen at 0x02C4EC60>]value=5
[<generator object gen at 0x02C4EC60>]value=6
[<generator object gen at 0x02C4EC60>]value=7
[<generator object gen at 0x02C4ED00>]value=0
[<generator object gen at 0x02C4ED00>]value=1
[<generator object gen at 0x02C4ED00>]value=2
[<generator object gen at 0x02C4ED00>]value=3
[<generator object gen at 0x02C4ED00>]value=4
[<generator object gen at 0x02C4ED00>]value=5
[<generator object gen at 0x02C4ED00>]value=6
[<generator object gen at 0x02C4ED00>]value=7
[<generator object gen at 0x02C4ED00>]value=8

总结如下:

  • 得到生成器的时候,并不会执行函数,只有当第一次调用next()方法的时候才会从函数的第一行开始执行
  • 在函数内执行代码的过程中,一旦遇到yield关键字就会立马停止运行,并返回yield后面的内容。下次再调用next()方法会激活生成器,并从yield代码的下面一行开始继续执行。如果后面还会遇到yield,重复前面描述的过程。直到函数中的代码被执行完毕,此时会抛出‘StopIteration’异常
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值