生成器介绍
在函数内部包含yield关键字,那么该函数执行的结果是生成器,生成器就是迭代器。
生成器的功能:把函数结果做成迭代器(以一种优雅的方式封装好iter,next)。提供了一种自己定义迭代器的方式。
使用生成器创建一个迭代器:
def a():
print('a')
yield 11 # 使用yield,执行后返回,类似于return,但是直接执行函数会生成一个迭代器
print('b')
yield 22
print('c')
yield '33'
g=a()
for i in g: # i=iter(g) g=next(i) #这里只执行迭代过程,迭代的内容是一个函数
pass
输出结果:
a
b
c
此处的i
做为迭代器中的一个元素,在执行之后会将yield
的返回值,赋值给i
,打印i
就可以得到返回值:
def a():
print('a')
yield 11
print('b')
yield 22
print('c')
yield '33'
g=a()
for i in g: # i=iter(g) next(i)
print(i)
执行结果:
a
11
b
22
c
33
生成器作用
使用生成器创建迭代器,在使用大容量列表或者对大文件进行操作的时候为了避免内存被耗尽会使用迭代器的方式去实现。
创建迭代器:
def my_rang(start,stop):
while True:
if start == stop:
raise StopIteration # 主动抛出一个异常,结束迭代器。
yield start
start+=1
g=my_rang(1,10)
for i in g:
print(i)
提示:不要使用控制循环的方式控制迭代器退出,这样会产生迭代器异常,最好使用主动抛出
raise StopIteration
的方式去终止迭代器。
yield与return的比较
都有返回值的功能,return只能返回一次值,yield能返回多次值。
yield的功能:
- 把函数的结果做成迭代器(以一种优雅的方式封装好iter,next)
- 函数暂停与再继续运行的状态是由yield提供的。
生成器与迭代器的应用
读取文件,模拟Linux 系统中的tail 功能。
import time
def tail(filename):
with open(filename,'r') as f:
f.seek(0,2)
while True:
line=f.readline()
if line:
yield (line)
else:
time.sleep(0.3)
for g in tail('a.txt'):
print(g)
当向文件中追加内容时,会自动显示追加的新内容。
同理,如果实现管道功能,使用grep类似的功能,只需添加一个grep 函数即可:
import time
def tail(filename):
with open(filename,'r') as f:
f.seek(0,2)
while True:
line=f.readline()
if line:
yield (line)
else:
time.sleep(0.3)
def grep(patten,lines):
for line in lines:
if patten in line:
print(line,end='')
grep('error',tail('a.txt'))
这样就避免了占用过大内存的情况,内存中只保存一行数据.