有趣的生成器-python

前言

这盘文章主要说明介绍了一下 python 中的生成器,yield 关键字

使用生成器的好处

1.生成器有惰性计算的特点,他运行的时候才会去执行

2.可以改变代码执行顺序,实现用户态程序块调度

样例及说明

1
2
3
4
5
6
7
8
9
10
11
12
def generator_func():
print 'function begin'
m = yield 1
print m
print "4"
n = yield 5
gen_obj = generator_func()
print gen_obj
print gen_obj.next()
print "2"
print gen_obj.send("3")
gen_obj.next()

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<generator object generator_func at 0x10f269190>
function begin
1
2
3
4
5
Traceback (most recent call last):
File "/Users/Grubby/Documents/pythonep/generator/yeild_test.py", line 12, in <module>
gen_obj.next()
StopIteration
[Finished in 0.1s with exit code 1]
[cmd: ['/usr/bin/python2', '-u', '/Users/Grubby/Documents/pythonep/generator/yeild_test.py']]
[dir: /Users/Grubby/Documents/pythonep/generator]
[path: /Library/Frameworks/Python.framework/Versions/3.5/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin:/usr/local/aria2/bin:/Applications/Wireshark.app/Contents/MacOS]

这是一个实际调用 python yield 的实例

1.generator object 的 next 方法和 send(None) 效果一样,也和 next(gen_obj) 效果一样

2.第一次调用 next() 方法,generator_func 函数才会运行起来,开始执行代码,直到碰到 yield 关键字

3.send 方法可以往里面塞值,会把值赋给里面的 yield 关键字的返回值

4.当生成器对象获取完后会抛出 StopIteration 异常

5.生成器可以用 for 语法来进行遍历,不会抛出 StopIteration 异常,但是只能调用next方法,不能用send

查看生成器状态

python3 中我们用 inspect 模块中的 getgeneratorstate 函数可以查看生成器的状态

GEN_CREATED 刚刚创建,还没执行过 GEN_SUSPENDED 暂停状态 GEN_CLOSED 生成器跑完了

生成器状态变为 GEN_CLOSED 有以下几种可能:

1.手工调用 close() 方法,gen_obj.close() 2.生成器运行完了抛出 StopIteration 异常 3.协程内部抛出了异常导致协程退出 4.协程调用.throw方法,显示要协程抛出任意异常

yield from 语法

在 python3 中,有特殊的 yield from 语法

1
2
3
4
5
6
def yield_from_func():
yield from "AB"
yield from "12"

my_gen = yield_from_func()
print(list(my_gen))

输出结果如下:

1
2
['A', 'B', '1', '2']
[Finished in 0.1s]

他实际上是先去调用 yield from x ,x 的 iter(x) 方法,把 x 变为一个迭代器,然后一个一个返回

yield 中的生产者消费者模型

这是一个很有趣的案例,在一个线程中依靠 yield 语法,实现生产者消费者模型

坚持原创技术分享,您的支持将鼓励我继续创作!