Python入门篇-生成器函数
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.生成器概述
1>.生成器generator
生成器指的是生成器对象,可以由生成器表达式得到,也可以使用yield关键字得到一个生成器函数,调用这个函数得到一个生成器对象
2>. 生成器函数
函数体中包含yield语句的函数,返回生成器对象 生成器对象,是一个可迭代对象,是一个迭代器 生成器对象,是延迟计算,惰性求值的 包含yield语句的生成器函数生成生成器对象的时候,生成器函数的函数体不会立即执行 next(generator)会从函数的当前位置向后执行到之后碰到的第一个yield语句,会弹出值,并暂停函数执行 再次调用next函数,和上一条一样的处理过程
没有多余的yield语句能被执行,继续调用next函数,会抛出StopIteration异常
3>.编写一个生成器函数样例
#!/usr/bin/env python
#_*_coding:utf-8_*_
#@author :yinzhengjie
#blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
#EMAIL:y1053419035@qq.com """
关于生成器函数的相关说明: 在生成器函数中,使用多个yield语句,执行一次后会暂停执行,把yield表达式的值返回 再次执行会执行到下一个yield语句 return 语句依然可以终止函数运行,但return语句返回值不能被捕获到 return 会导致无法继续获取下一个值,抛出StopIteration异常 如果函数没有显示的return语句,如果生成器函数执行到结尾,一样会抛出StopIteration异常哟 """
def gen():
print('line 1')
yield 1
print('line 2')
yield 2
print('line 3')
return 3 next(gen()) next(gen()) g = gen() print(next(g))
print(next(g)) # print(next(g)) #报错:StopIteration: 3,因为已经没有多余的yield语句啦,上面已经被调用两次了 print(next(g, 'End')) #如果没有元素就给个缺省值 #以上代码执行结果如下:
line 1
line 1
line 1
1
line 2
2
line 3
End
二.生成器应用
1>.无限循环
#!/usr/bin/env python
#_*_coding:utf-8_*_
#@author :yinzhengjie
#blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
#EMAIL:y1053419035@qq.com def counter():
i = 0
while True:
i += 1
yield i def inc(c):
return next(c) c = counter() #这是一个生成器对象 print(inc(c))
print(inc(c)) #以上代码输出结果如下:
1
2
2>.计数器
#!/usr/bin/env python
#_*_coding:utf-8_*_
#@author :yinzhengjie
#blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
#EMAIL:y1053419035@qq.com def inc():
def counter():
i = 0
while True:
i += 1
yield i
c = counter()
return lambda : next(c) #这里返回的是匿名函数 foo = inc()
print(foo())
print(foo()) #以上代码输出结果如下:
1
2
3>.处理递归问题
#!/usr/bin/env python
#_*_coding:utf-8_*_
#@author :yinzhengjie
#blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
#EMAIL:y1053419035@qq.com def fib():
x = 0
y = 1
while True:
yield y
x, y = y, x+y foo = fib() for _ in range(5):
print(next(foo)) for _ in range(100):
next(foo) print(next(foo)) #以上代码输出结果如下:
1
1
2
3
5
6356306993006846248183
#!/usr/bin/env python
#_*_coding:utf-8_*_
#@author :yinzhengjie
#blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
#EMAIL:y1053419035@qq.com pre = 0
cur = 1
print(pre,cur,end=" ") def fib(n,pre=0,cur=1):
pre,cur = cur,pre + cur
print(cur,end=" ")
if n == 2:
return
fib(n-1,pre,cur) fib(106)
以上代码改写成递归方式戳我~
4>.协程(coroutine)
(1)生成器的高级用法 (2)比进程,线程轻量级 (3)是在用户空间调度的一种实现 (4)Python3 asyncio就是协程实现,已经加入到标准库 (5)Python3.5 使用async,await关键字直接原生支持协程
协程调度器实现思路:
有2个生成器A,B
next(A)后,A执行到了yield语句暂停,然后去执行next(B),B执行到yield语句也暂停,然后再次调用next(A),再调用next(B),周而复始,就实现了调度的效果
可以引入调度的策略来实现切换的方式 (6)协程就是一种非抢占式调度
三.yield from
#!/usr/bin/env python
#_*_coding:utf-8_*_
#@author :yinzhengjie
#blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
#EMAIL:y1053419035@qq.com def inc():
for x in range(1000):
yield x foo = inc()
print(next(foo))
print(next(foo))
print(next(foo)) print("*" * 20 + "我是分割符" +"*" * 20) """
以上代码可以使用yield from代码改写,等价于下的代码:
"""
def inc():
yield from range(1000) bar = inc()
print(next(bar))
print(next(bar))
print(next(bar)) #以上代码输出结果如下:
0
1
2
********************我是分割符********************
0
1
2
#!/usr/bin/env python
#_*_coding:utf-8_*_
#@author :yinzhengjie
#blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
#EMAIL:y1053419035@qq.com """
yield from是Python 3.3出现新的语法 yield from iterable 是 for item in iterable: yield item 形式的语法糖 """ #从可迭代对象中一个个拿元素
def counter(n):
for x in range(n):
yield x def inc(n):
yield from counter(n) foo = inc(10)
print(next(foo))
print(next(foo)) #以上代码执行结果如下:
0
1
yield from是Python 3.3出现新的语法