初次编辑2017年10月27日,星期五
摘要
引用:Alex
- 迭代器
- 生成器
- 协程函数
一. 上节课复习
- 装饰器
- 无参装饰器
- 有参装饰器
- 装饰器打印原函数信息
import time
from functools import wraps #注意这个
def timmer(func):
@wraps(func) #还有这个
def wrapper():
start_time = time.time()
func()
stop_time = time.time()
print('run time is %s ' % (stop_time - start_time))
return wrapper
@timmer #index=timmer(index)
def index():
'come from index'
print('welcome to oldboy')
index() #wrapper()
print(index.__doc__) #.__doc__打印函数描述信息,具体不是很了解
二. 迭代器
- 可迭代的
- 只要对象本身有__iter__方法,那它就是可迭代的
- 迭代器
- i = a.iter() #i 即为迭代器
- 可通过__next__ 进行取值
b = {'a':1,'b':2,'c':3}
i = iter(b)
while True:
print(next(i))
#注意:此方法会while会无限循环,报错异常 StopIteration
- 异常捕捉
b = {'a':1,'b':2,'c':3}
i = iter(b)
while True:
try: #注意此行
print(next(i))
except StopIteration: #and this
break # and this
- for 循环机制
for key in d: #d即为d.__iter__() 迭代器放入原位置
print(key) #并且for循环具有异常捕捉的功能
- for 循环实现迭代器
b = {'a':1,'b':2,'c':3}
for i in b:
print(i)
- 为什么要用迭代器
- 优点
- 迭代器提供了一种不依赖于索引的取值方式,这样就可以遍历那些没有索引的可迭代对象了(字典、集合、文件)
- 迭代器与列表相比,迭代器是惰性计算的,更省内存(迭代器在内存中同一时刻只有一个值)
- 缺点
- 无法获取迭代器的长度,使用不如列表索引取值灵活
- 一次性的,只能往后取值,不能倒着取值
- 优点
- 查看可迭代对象与迭代器对象
from collections import Iterable,Iterator
s = 'hello'
l = [1,2,3]
t = (1,2,3)
d = {'a':1}
set1 = (1,2,3,4)
f = open('a.txt')
s.__iter__()
l.__iter__()
t.__iter__()
d.__iter__()
set1.__iter__()
f.__iter__()
#Iterable 为可迭代的
print(isinstance(s,Iterable)) #isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。
print(isinstance(l,Iterable))
print(isinstance(t,Iterable))
print(isinstance(d,Iterable))
print(isinstance(set1,Iterable))
print(isinstance(f,Iterable))
- 查看是否是迭代器
print(isinstance(s,Iterator)) #Iterator 为迭代器
print(isinstance(l,Iterator))
print(isinstance(t,Iterator))
print(isinstance(d,Iterator))
print(isinstance(set1,Iterator))
print(isinstance(f,Iterator))
三. 生成器
- 定义:生成器就是一个函数,这个函数内包含有yield这个关键字,可以将函数变成具有序列性,返回多个值
- 生成器与return有何区别
- return只能返回一次函数就彻底结束了,而yield能返回多次值
- yield到底干了什么事
- yield把函数变成生成器(生成器其实就是迭代器)(yield将__next__和__iter__封装到函数内部)
- 用return返回只能返回一次,而yield返回多次
- 函数在暂停以及继续下一次运行时的状态是由yield保存
def test():
print('one')
yield 1
print('two')
yield 2
print('three')
yield 3
g = test() #无输出,此时g为生成器,即把函数变成一个迭代器
print(g) #<generator object test at 0x00000000027E91A8>
res = next(g) #one next触发生成器的执行
print(res) #1
- yield具体应用
def countdown(n):
print('start countdown')
while n >0:
yield n
n -= 1
print('done')
g= countdown(5)
print(next(g)) #start countdown 5
print(next(g)) #4
print(next(g)) #3
print(next(g)) #2
print(next(g)) #1
print(next(g)) #done #会报错
#for循环写法
for i in g:
print(i)
#while循环写法
while True:
try:
print(next(g))
except StopIteration:
break
- 生成器应用
#惰性计算
def func():
n = 0
while True:
yield n
n += 1
f = func()
print(next(f))
- tail命令的最基本实现
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.5)
continue
else:
print line, #print 输出光标不换行
tail('/tmp/a.txt')
- tail命令通过生成器实现(python2)
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.5)
print '======='
continue
else:
yield line
g = tail('/tmp/a.txt') #函数变成一个生成器
for line in g:
print line,
- grep命令通过生成器实现(python2)
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.5)
continue
else:
yield line
g = tail('/tmp/a.txt')
for line in g:
if 'error' in line:
print line,
- grep命令通过生成器实现且有水流概念
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.5)
continue
else:
yield line
def grep(pattern,lines): #pattern 为grep所抓取的 lines为输入源
for line in lines:
if pattern in line:
print line,
g = tail('/tmp/a.txt')
grep('error',g)
- tail、grep命令最终版
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.5)
continue
else:
yield line
def grep(pattern,lines): #pattern 为grep所抓取的 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,
四. 协程函数
- 吃包子
def eater(name):
print('%s start to eat food '% name)
food_list = []
while True:
food = yield food_list
print('%s get %s, to start eat '% (name, food))
food_list.append(food)
print('Done')
e = eater('钢蛋')
print(next(e))
print(e.send('包子'))
print(e.send('韭菜包子')) #send 等同于next 有返回值,但是会把后面的参数传给当前行的yield
print(e.send('馅饼'))
作业
- 无
今日总结
- 待整理
<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">