Python 生成器

1 生成器

1.1 生成器定义

生成器就是一个函数,有yield关键字,主要是针对函数的

1
2
3
4
5
6
7
8
9
from collections import Iterable,Iterator
def test():
print("test")
yield 1
yield 2
g = test()
print(g)
print(isinstance(g,Iterator)) # 判断是否是迭代器对象

结果:
generator object test at 0x00000000027FC780
True

返回结果是证明生成器就是迭代器

证明了是迭代器,迭代器可以用next()执行,这里就是next(g)

1
print(next(g))

结果是:
test
1

结果是执行了一个test,并返回了一个1

再写一条print(next(g)),

结果是:
test
1
2

小结:

生成器是一个有yield 的函数,想要使用就要用next()f方法,运行一次next后会程序会停在yield,再次执行的时,会从yield这个位置继续向下执行。

1.2 生成器中的yield和函数return的区别

函数的返回值return的区别
return只能执行一次,函数就彻底结束
yield可以返回多次值
yield 可以保存运行状态
函数在暂停以及继续运行的状态是yield保存的
yield相当于把iternext 方法

1.3 生成器—>迭代器 for循环

1
2
3
4
5
6
7
8
9
10
from collections import Iterable,Iterator
def test():
print("test")
yield 1,2,3
yield 2
g = test()
for i in g: # g是迭代器
print(i)

结果:
test
(1, 2, 3)
2

yield 返回值是多个的时候,返回的是元组

牛逼之处:

自己能够定义一个函数,然后控制函数的返回值,把函数构造成一个序列类型,能够被for遍历

遇到迭代器,就用next()

1.4 迭代器计数

1
2
3
4
5
6
7
8
9
10
11
12
13
def countdown(n):
print("start")
while n > 0:
yield n
n -=1
print('done')
g = countdown(5)
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))

这种情况下,但n=0的时候,有next就会找yield,但是最后不能进入while循环了,所以会报错

for循环的形式:

1
2
3
4
5
6
7
8
9
10
def countdown(n):
print("start")
while n > 0:
yield n
n -=1
print('done')
g = countdown(5)
for i in g:
print(i)

2 Python制作动态查看文件的内容—tail工具

tail -f 查看文件的时候,是一直在等待,直到有内容增加进来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#/usr/bin/env python
import time
def tail(file_path):
with open(file_path,'r') as f:
f.seek(0,2)
while True:
line = f.readline()
if not line:
time.sleep(0.3)
continue
else:
print(line,end='')
tail('/tmp/a.txt') # 这是传入的文件的路径

这里遇到的问题是在open文件的时候,file_path加上了引号,就是思维定式了,不知道这里传入的是一个参数。

使用生成器的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#/usr/bin/env python
import time
def tail(file_path):
with open(file_path,'r') as f:
f.seek(0,2)
while True:
line = f.readline()
if not line:
time.sleep(0.3)
continue
else:
yield line
g = tail('/tmp/a.txt') # 这是传入的文件的路径
for i in g:
print(i,end='')

过滤动态添加的内容

使用的是管道的概念

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#/usr/bin/env python
import time
def tail(file_path):
with open(file_path,'r') as f:
f.seek(0,2)
while True:
line = f.readline()
if not line:
time.sleep(0.3)
continue
else:
yield line
g = tail('/tmp/a.txt') # 这是传入的文件的路径
for i in g:
if ‘error’ in i:
print(i,end='')

通过添加判断能够过滤到error,但是这样就是写死了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#/usr/bin/env python
import time
def tail(file_path):
with open(file_path,"r",encoding="utf-8") as f:
f.seek(0,2) # 把光标放到文件的最后的第0个字节
while True:
line = f.readline() # 读每一行的内容
if not line:
time.sleep(0.5)
continue # 当没有数据传入的时候,跳过这一次
else:
# print(line,end='') # python3
# print(line,) # python2
yield line
def grep(pattern,lines): # lines是接收的
for line in lines:
if pattern in line: # pattern 是要过滤的内容
print(line,end='')
#for i in g:
# if 'error' in i:
# print(i,end='')
g = tail('/tmp/a.txt')
grep('error',g)

把grep写成生成器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#/usr/bin/env python
import time
def tail(file_path):
with open(file_path,"r",encoding="utf-8") as f:
f.seek(0,2) # 把光标放到文件的最后的第0个字节
while True:
line = f.readline() # 读每一行的内容
if not line:
time.sleep(0.5)
continue # 当没有数据传入的时候,跳过这一次
else:
# print(line,end='') # python3
# print(line,) # python2
yield line
def grep(pattern,lines): # lines是接收的
for line in lines:
if pattern in line: # pattern 是要过滤的内容
#print(line,end='')
yield line
# 调用阶段 得到两个生成器
g1 = tail('/tmp/a.txt')
g2 =grep('error',g1)
# 触发执行阶段
for i in g2:
print(i)
© 2018 Peter's Blog Center All Rights Reserved.
Theme by hiero