迭代器 生成器
一 什么是迭代器协议
1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退)
2.可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)
3.协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象。
1
2
3
4
5
6
7
|
#序列类型 字符串,列表,元组都有下标,你用上述的方式访问 #非序列类型 字典,集合,文件 #for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法, #即在遍历之前,先调用对象的__iter__方法将其转换成一个迭代器, #然后使用迭代器协议去实现循环访问,这样所有的对象就都可以通过for循环来遍历了, #而且你看到的效果也确实如此,这就是无所不能的for循环,觉悟吧,年轻人 |
迭代器
1
2
3
|
#可迭代的:只要对象本身有__iter__方法,那它就是可迭代的 #执行对象下的__iter__方法,得到的结果就是迭代器 |
为什么要用迭代器:
1
2
3
4
5
6
7
|
#优点 # 1:迭代器提供了一种不依赖于索引的取值方式,这样就可以遍历那些没有索引的可迭代对象了(字典,集合,文件) # 2:迭代器与列表比较,迭代器是惰性计算的,更节省内存 #缺点: # 1:无法获取迭代器的长度,使用不如列表索引取值灵活 # 2:一次性的,只能往后取值,不能倒着取值 |
迭代器的用途
1
|
for 循环
|
二.生成器
一.函数
1.什么是生成器?
1
|
可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他的数据类型需要调用自己内置的__iter__方法),所以生成器就是可迭代对象 |
2.生成器分类及在python中的表现形式:(Python有两种不同的方式提供生成器)
1
2
3
4
|
1. 生成器函数:常规函数定义,但是,使用 yield 语句而不是 return 语句返回结果。 yield 语句一次返回一个结果,在每个结果中间,挂起函数的状态,
以便下次重它离开的地方继续执行 2. 生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
|
3.为何使用生成器之生成器的优点
1
2
|
Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。 这也是生成器的主要好处。 |
4.生成器小结:
1
2
3
|
1. 是可迭代对象
2. 实现了延迟计算,省内存啊
3. 生成器本质和其他的数据类型一样,都是实现了迭代器协议,只不过生成器附加了一个延迟计算省内存的好处,其余的可迭代对象可没有这点好处,记住喽!!!
|
5.yield的功能:
1
2
3
|
1. 相当于把__iter__和__next__方法封装到函数内部
2. 与 return 比, return 只能返回一次,而 yield 能返回多次
3. 函数暂停已经继续运行的状态是通过 yield 保存的
|
#yield表达形式:
food=yield #生成器.send与next(生成器)区别:
1.如果函数内yeild是表达式形式,那么必须先next(e)
2.二者的共同之处都可以让函数在上次暂时的位置继续运行不同之处在于send在出发下一次的执行时,会顺便给yield传一个值 yield表达式
yield表达式
tail 命令实现
#/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='')
yield line def grep(pattern,lines):
for line in lines:
if pattern in line:
yield line #调用阶段:得到俩生成器对象
g1=tail('/tmp/a.txt')
g2=grep('error',g1) #next触发执行g2生成器函数
for i in g2:
print(i) tail -f /tmp/a.txt | grep error
二.生成器表达式
#三元表达式
name='alex'
name='linhaifeng'
res='SB' if name == 'alex' else 'shuai'
print(res) #列表解析
li = [i for i in range(10) ]
li = [i for i in range(10) if i > 5]
三.协程
def init():
def wrapper(*args,**kwargs):
obj = func(*args,**kwargs)
next(obj)
return obj
return wrapper @init #food = init(food)
def food(name):
print("%s start to eat" % name)
food_list = []
while True:
food = yield food_list
food_list.append(food)
print("%s eat %s" % (name,food_list)) e = food("alex")
e.send("apple")
e.send("apple")
e.send("apple") 协程包子
协程包子
#grep -rl 'python' C:\egon
import os,time
def init(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
next(res)
return res
return wrapper #找到一个绝对路径,往下一个阶段发一个
@init
def search(target):
'找到文件的绝对路径'
while True:
dir_name=yield #dir_name='C:\\egon'
print('车间search开始生产产品:文件的绝对路径')
time.sleep(2)
g = os.walk(dir_name)
for i in g:
# print(i)
for j in i[-1]:
file_path = '%s\\%s' % (i[0], j)
target.send(file_path) @init
def opener(target):
'打开文件,获取文件句柄'
while True:
file_path=yield
print('车间opener开始生产产品:文件句柄')
time.sleep(2)
with open(file_path) as f:
target.send((file_path,f)) @init
def cat(target):
'读取文件内容'
while True:
file_path,f=yield
print('车间cat开始生产产品:文件的一行内容')
time.sleep(2)
for line in f:
target.send((file_path,line)) @init
def grep(pattern,target):
'过滤一行内容中有无python'
while True:
file_path,line=yield
print('车间grep开始生产产品:包含python这一行内容的文件路径')
time.sleep(0.2)
if pattern in line:
target.send(file_path) @init
def printer():
'打印文件路径'
while True:
file_path=yield
print('车间printer开始生产产品:得到最终的产品')
time.sleep(2)
print(file_path) g=search(opener(cat(grep('python',printer()))))
g.send('C:\\egon')
g.send('D:\\dir1')
g.send('E:\\dir2') 协程windows 查找文件
协程windows 查找文件
import os def init(func):
def wrapper(*args,**kwargs):
obj = func(*args,**kwargs)
next(obj)
return obj
return wrapper @init
def search(target):
while True:
dir_name = yield
obj = os.walk(dir_name)
for file in obj:
for path in file[-1]:
file_path = "%s/%s" % (file[0],path)
target.send(file_path) @init
def opener(target):
while True:
file_path = yield
with open(file_path) as f:
target.send((file_path,f))
@init
def cat(target):
while True:
file_path,file = yield
for line in file:
target.send((file_path,line))
@init
def grep(pattern,target):
while True:
file_path,line = yield
if pattern in line:
target.send(file_path)
@init
def print_file():
while True:
file_path = yield
print(file_path) g = search(opener(cat(grep("a",print_file()))))
g.send("/Users/centos/Desktop/example") 协程Linux查找文件
协程Linux查找文件
四.Example 两题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
def cat(name):
with open ( "a" , "r" ,encoding = "utf8" ) as name:
for line in name:
yield line
def grep(target,lines):
for line in lines:
if target in line:
yield line
line_cat = cat( "a" )
grep_cat = grep( "apple" ,line_cat)
for line in grep_cat:
print (line.strip())
|
1
2
3
4
5
6
7
8
9
10
|
from urllib.request import urlopen
def get():
while True :
url = yield
res = urlopen(url).read()
print (res)
g = get()
next (g)
g.send( 'http://www.python.org' )
|
http://www.cnblogs.com/linhaifeng/articles/6133014.html