迭代器
先看一个这样的示例
1 | class Company: |
这样原来的实例就可以遍历了,__getitem__
有个参数item
就是迭代的索引,这是因为编译器自动在内部自动生成了迭代器,相当于如下代码
1 | from collections.abc import Iterator |
但是我们明明抛出异常了,但是并没有捕获处理啊!这是因为for in
内部已经处理了
for in
相当于转化为了如下代码:
1 | class Company: |
生成器
示例
只要方法中有yield
,就会被解析为生成器
1 | import dis |
其中
g = gen_func()
获取生成器对象
dis.dis(g)
能查看生成器对象的字节码执行过程
g.gi_frame.f_lasti
能查看字节码执行的行号
g.gi_frame.f_locals
能查看当时的环境变量
结果
1 | 3 0 LOAD_CONST 1 ('小红') |
我们可以用for来遍历生成器的结果
1 | def gen_func(): |
结果
1 | 小红 |
可以看出我们只能接收yield返回的值
输入参数
1 | def consumer(): |
结果
1 | c.send(None): |
注意
生成器必须
c.send(None)
来启动,如果启动前直接c.send(1)
会报错,启动的时候会先yield
一次数据。
之后会按照如图1,2,3的顺序运行。
c.close()
能够关闭生成器。
生产和消费
我们能发现程序在两个方法之前,来回切换,协程就是利用这个方式实现的。
1 | def consumer(): |
结果
1 | [PRODUCER] Producing 1... |
读取文件
读取多行文件
1 | aaaaaa |
读取
1 | with open("input.txt") as f: |
读取单行大文件
假如文件只有一行,并且文件较大,有固定的分隔符
1 | aaaaaa[|]bbb[|]ccc[|]dd |
读取代码
1 | def myreadlines(f, separator): |