迭代器和生成器
一迭代器
1.1)什么是可迭代?
凡是可以使用for循环取值的都是可迭代的
列表 字典 元祖 字符串 集合 range 文件句柄 enumerate 这些都是可迭代的
for i in (1,2,3,4):
print(i)
1.2)可迭代协议
可迭代协议:内部含有_iter_方法都是可迭代的
迭代器协议:内部含有_next_方法都是迭代器
迭代器的优势
节省内存
#快
# 取一个值就进行接下来计算,二不需要等到所有的值都计算出来才开始接下来的运算-快
from collections import Iterable,Iterator
print(range(1,10000))
print(isinstance(range(10000),Iterable))
print(isinstance(range(10000),Iterator))
迭代器的特性:惰性运算
二、生成器
一个包含yield关键字的函数就是一个生成器函数。
yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。
每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。
生成器的例子
假如我想让工厂给学生做校服,生产2000000件衣服,我和工厂一说,工厂应该是先答应下来,然后再去生产,我可以一件一件的要,也可以根据学生一批一批的找工厂拿。
而不能是一说要生产2000000件衣服,工厂就先去做生产2000000件衣服,等回来做好了,学生都毕业了。。。
def cloth(num): for i in range(num): yield ("生产第%s件衣服" %i)#记录当前所在的位置,等待下一次next来触发函数的状态 # print("生产第%s件衣服" %i) # g=cloth(5) for i in g: print(i)
g=cloth(5)
for i in g:
print(i)
# print(next(g))
# print(next(g))
生成器函数的调用不会触发代码的执行,而是会返回一个生成器(迭代器0
想要生成器函数执行要用next
生成器的应用
#使用生成器来监听文件
import time
def listener_files():
with open('access.log',mode='r',encoding='utf-8') as f:
while True:
line=f.readline()
if line.strip():
yield line.strip()
else:
time.sleep(1)
g=listener_files()
for line in g:
print(line)
2.计算移动工资
def agv_monery(): sum_monery=0 day=0 argv_moeny=0 while True: monery=yield argv_moeny day += 1 sum_monery +=monery argv_moeny=sum_monery/day g=agv_monery() print(next(g)) print(g.send(300)) print(g.send(500))
三、列表推导式和生成器表达式
1.列表推导式
#老男孩由于峰哥的强势加盟很快走上了上市之路,alex思来想去决定下几个鸡蛋来报答峰哥 egg_list=['鸡蛋%s' %i for i in range(10)] #列表解析 #峰哥瞅着alex下的一筐鸡蛋,捂住了鼻子,说了句:哥,你还是给我只母鸡吧,我自己回家下 laomuji=('鸡蛋%s' %i for i in range(10))#生成器表达式 print(laomuji) print(next(laomuji)) #next本质就是调用__next__ print(laomuji.__next__()) print(next(laomuji))
1.1)30以内所有能被3整除的数
multiples = [i for i in range(30) if i % 3 is 0] print(multiples) # Output: [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
1.2)30以内所有能被3整除的数的平方
res=([num**2 for num in range(1,30) if num%3==0]) print(res)
1.3)找到嵌套列表中名字含有两个‘e’的所有名字
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
print([ name for list in names for name in list if name.count('e') >=2])
2.生成器表达式
2.1 找到嵌套列表中名字含有两个‘e’的所有名字
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'], ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']] g=( name for list in names for name in list if name.count('e') >=2) for i in g: print(i)
2.2 30以内所有能被3整除的数
g=(i for i in range(30) if i%3==0) for i in g: print(i)
2.3 30以内所有能被3整除的数的平方
g=(num **2 for num in range(30) if num%3==0) for i in g: print(i)
3总结列表推导式和生成器表达式
1.把列表解析的[]换成()得到的就是生成器表达式
2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存
3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。
4.其他推导式
4.1字典推导式
1)将一个字典的key和value对调
mcase = {'a': 10, 'b': 34} mcase_frequency = {mcase[k]: k for k in mcase} print(mcase_frequency)
2)合并大小写对应的value值,将k统一成小写
mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3} mcase_frequency = {k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase.keys()} print(mcase_frequency)
4.2集合推导式
4.2.1计算列表中每个值的平方,自带去重功能
set1={i**2 for i in [-1,1,2,3]} print(set1)
4.3练习题
4.3.1)过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'], ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']] #集合推导式 set2={ name for list in names for name in list if len(name) >3 } print(set2) #列表推导式 list1=[ name for list in names for name in list if len(name) >3] print(list1) #生成器表达式 g=(name for list in names for name in list if len(name) >3) for i in g: print(i)
4.3.2.求(x,y)其中x是0-5之间的偶数,y是0-5之间的奇数组成的元祖列表
#列表推导式 l1=[ (x,y)for x in range(5) if x%2==0 for y in range(5) if y%2==1] print(l1) #生成器表达式 g=((x,y)for x in range(5) if x%2==0 for y in range(5) if y%2==1) for i in g: print(i) #集合推导式 set22={(x,y)for x in range(5) if x%2==0 for y in range(5) if y%2==1} print(set22)
4.3.3 求M中3,6,9组成的列表M = [[1,2,3],[4,5,6],[7,8,9]]
#求M中3,6,9组成的列表M = [[1,2,3],[4,5,6],[7,8,9]] M = [[1,2,3],[4,5,6],[7,8,9]] print([list[-1] for list in M ])
四、生成器相关面试题
def demo(): for i in range(4): yield i g=demo() g1=(i for i in g) g2=(i for i in g1) print(list(g1)) print(list(g2))
def add(n,i): return n+i def test(): for i in range(4): yield i g=test() for n in [1,10]: g=(add(n,i) for i in g) print(list(g))
import os def init(func): def wrapper(*args,**kwargs): g=func(*args,**kwargs) next(g) return g return wrapper @init def list_files(target): while 1: dir_to_search=yield for top_dir,dir,files in os.walk(dir_to_search): for file in files: target.send(os.path.join(top_dir,file)) @init def opener(target): while 1: file=yield fn=open(file) target.send((file,fn)) @init def cat(target): while 1: file,fn=yield for line in fn: target.send((file,line)) @init def grep(pattern,target): while 1: file,line=yield if pattern in line: target.send(file) @init def printer(): while 1: file=yield if file: print(file) g=list_files(opener(cat(grep('python',printer())))) g.send('/test1')
本文来自博客园,作者:鱼丸粗面没鱼丸,转载请注明原文链接:https://www.cnblogs.com/Robi-9662/p/8976935.html