基础概念迭代器: 为什么: 提供了一种不依赖于索引的取值方式,如字典,集合,文件等没有索引的类型需要循环取出元素 迭代器是惰性计算,更节省内存,迭代器在内存中只是一个内存地址,一次只取一个值 缺点:永远无法获取迭代器的长度,使用不如列表索引取值灵活 一次性的,只能往后取值 可迭代的:对象本身有__iter__方法 i = iter(n) or i = n.__iter__() i 为n的迭代器 next(i) or i.__next__() 利用迭代器输出内容,一次输出一个 生成器: 定义: 函数中包含yield语句 将生成器函数(有yield)返回的g作为迭代器使用,这个g就是生成器, 每次next生成器,就执行一次函数 即 将整个函数作为迭代器 yield与return 的区别: return只能执行一次函数就彻底结束,yield 能多次返回值 yield的作用: 把函数的返回值变成迭代器 ---------》生成器 将iter next函数封装到函数内部, 将函数变为一个迭代器对象(将函数变成了一个类似序列类型的对象) 多次输出函数运行结果 每次触发就运行一次函数,保存函数在暂停及继续下一次运行时的状态 协程函数 本质是一种生成器函数,函数中的yield由表达式所写 面向过程编程的主要形式 e.send() 与 next(e)的区别: 二者的共同之处是度可以让函数在上次暂停的位置继续运行 二者都可以返回yield后面的返回值 如果函数内yield是表达式形式,那么必须先next(e) send在触发下一次next的时候会给上次的yield传值所有的生成器函数都只能通过next send 和for循环来逐次运行函数,且生成器函数本身不会运行 迭代器 与生成器的相同:生成器是迭代器的一种,生成器具有迭代器全部的功能 惰性计算 不同: 迭代器只是每次返回一个已知序列的值 生成器保存了一个算法,比迭代器多了一个功能是边运行边计算,返回一个运算过的序列的值 迭代器---------->生成器---------->生成器的表达式应用:协程函数----------->面向过程的编程:利用了函数式编程的思想
l = [‘a‘,‘b‘,‘c‘,‘d‘]#while循环列表i =0while i < len(l): print(l[i]) i += 1# for 循环列表for i in range(len(l)): #使用索引取出元素 print(l[i]) for i in l: #使用for自带的迭代器取出元素 print(i) d = {‘a‘:1,‘b‘:2,‘c‘:3}#while 循环字典g = d.__iter__() #迭代器gprint(type(g))while True: try: #捕捉异常 print(next(g)) #迭代器的方法__next__() except StopIteration: break #for 循环字典 for i in g: #g已经是一个迭代器,但for循环中的自动转迭代器不会影响遍历字典 print(i) for i in d: #for循环内包含了iter ,next ,和 自动捕捉异常的函数 print(i) #while循环文件while True: try: print(next(f)) except StopIteration: break#for循环文件with open(‘a.txt‘) as f: for line in f: print(line.strip()) f = open(‘a.txt‘)f.__iter__() #文件本身就是一个迭代器print(f.__next__()) s = ‘hello‘l = [1,2,3]t = (1,2,3)d = {‘a‘:1}s = {‘a‘,‘b‘}f = open(‘a.txt‘)# 查看可迭代对象from collections import Iterables.__iter__()print(isinstance(l,Iterable))#查看迭代器对象from collections import Iteratorf.__next__()print(isinstance(l,Iterator)) #生成器def test(): #生成器函数 print(‘one‘) yield 1 print(‘two‘) yield 2 print(‘three‘) yield 3 print(‘four‘) yield 4 print(‘five‘)g = test() #返回一个生成器 同时也是一个迭代器,可以作为迭代器使用 g.__next__()g.__next__()g.__next__()g.__next__()#生成器的应用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)) while True: try: print(next(g)) except StopIteration: break for i in g: print(i)#生成器有个迭代器的属性:惰性计算 如下函数 生成器可以一直运行,而且内存不会卡def func(): n = 0 while True: yield n n += 1g = func()#print(next(f))for i in g: print(i) print(isinstance((x for x in range(10)),Iterable))#生成器应用:随时监听文件中的错误日志#/usr/bin/env pythonimport timedef tail(file_path): with open(file_path) as f: f.seek(0,2) while True: line = f.readline() if not line: time.sleep(0.5) continue else: #print(line,end=‘‘) yield linedef grep(pattern,lines): for line in lines: if pattern in line: yield lineg1=tail(‘/tmp/a.txt‘)g2=grep(‘error‘,g1)for i in g2: print(i) #生成器的表达式应用:协程函数def eater(name): print(‘%s start to eat food‘%name) food_list=[] while True: #必须加while循环,为每次生成器发送的值创造循环条件 food = yield food_list print(‘%s got %s to start eat‘%(name,food)) food_list.append(food) print(‘done‘) e = eater(‘gangdan‘) print(next(e))print(e.send(‘baozi‘)) #生成器在向函数发送参数时,以元组的形式发送,所以发送多个参数时,要加上()表示元组print(e.send(‘miantiao‘))print(e.send(‘mifan‘)) #为生成器添加装饰器def nextn(func): def wrapper(*args,**kwargs): res = func(*args,**kwargs) next(res) return res return wrapper@nextndef eater(name): print(‘%s start to eat food‘%name) food_list=[] while True: food = yield food_list print(‘%s got %s to start eat‘%(name,food)) food_list.append(food) print(‘done‘) e = eater(‘liuliu‘)e.send(‘baozi‘)
#迭代器应用:实现功能 cat a,txt | grep appleimport timedef cat(): while True: with open(‘a.txt‘) as f: lines = f.readline() if not lines: time.sleep(1) continue else: yield lines def grep(pattern,lines): for i in lines: if pattern in i: print(i) exit() g = cat()grep(‘apple‘,g) #生成器应用: 把下面的函数改成生成器的形式,执行生成器函数得到一个生成器g,然后每次g.send(url),# 打印页面内容,利用g可以无限sendfrom urllib.request import urlopendef opener(url): while True: print(urlopen(url).read()) url=yieldg = opener(‘http://www.baidu.com‘)next(g)g.send(‘http://www.360.com‘) def get(url): while True: def index(): res = urlopen(url).read() print(res) index() url = yield g = get(‘http://www.baidu.com‘)next(g)g.send(‘http://www.360.com‘)
时间: 2024-10-20 11:41:54