# 迭代器和生成器 # 迭代器: # 双下方法:很少用 ,一般是通过其他方法触发的 # 可迭代协议——含有__iter__方法 # 迭代器协议——含有__iter__和__next__方法 # 可迭代的一定可以for循环 # 迭代器一定可迭代,可迭代对象通过调用__iter__方法就可得到一个生成器 # 迭代器特点 # 方便使用,但是迭代器中的数据只能取一次 # 节省内存空间 # 生成器: # 本质上就是一个迭代器 # 生成器的表现形式 # 生成器函数 # 含有yield关键字的函数就是生成器函数 # 特点: # 调用函数之后,返回一个生成器 # 每次调用next方法的时候就会取到一个值 # 知道取完最后一个值再执行next就会报错 # 取值方法: # next # for # 数据类型的强制转换;此方法占内存 # 生成器表达式 # def generator(): # for i in range(200): # yield "哇哈哈%s"%i # g = generator() # ret = list(g) #数据类型强制转换,占内存 # print(ret) # g = generator() #调用函数得到一个生成器 # print(g) # ret = g.__next__() # print(ret) # num = 0 # for i in g: # num += 1 # if num >50: # break # print(i) # def generator(): # print(123) # content = yield 1 # print('====',content) # print(456) # arg = yield 2 # g1=generator() # g2=generator() # g1.__next__() # g2.__next__() # print('***',generator().__next__()) # print('***',generator().__next__()) # g = generator() # ret = g.__next__() # print('***',ret) # ret = g.send('hello') # print('***',ret) # send: # send获取下一个值的效果和next基本一致 # 只是在获取下一个值时,同时给上一个yield位置出传递一个参数 # 使用send的注意事项: # 第一次使用生成器时,只能用next获取下一个值 # 最后一个yield无法接受外部值 # 计算移动平均值 avg = sum/count # 10 20 30 # 10 15 20 # def average(): # sum = 0 # count = 0 # avg = 0 # while True: # num = yield avg # sum +=num # count+=1 # avg = sum/count # g = average() # g.__next__() #激活发生器 # g1 = g.send(10) #执行到下一个yield才结束 # print(g1) # g1=g.send(20) # print(g1) # 升级版,用一个装饰器去预激活一个生成器 # def actter(func): # def inner(*args, **kwargs): # ret = func(*args, **kwargs) # ret.__next__() #在此激活生成器 # return ret # # return inner # # @actter # def average(): # sum = 0 # count = 0 # avg = 0 # while True: # num = yield avg # sum += num # count += 1 # avg = sum / count # # g = average() # ret = g.send(10) # print(ret) # ret = g.send(90) # print(ret) # def l(): # yield from range(20) # print(list(l())) # 列表解析 # egg_list=['鸡蛋%s'%i for i in range(10)] # #[存入方式 循环体 循环条件(可以有多个)] # print(egg_list) # egg_list = [] # for i in range(1000): # egg_list.append('鸡蛋%s' % i) # print(egg_list) # print([i*i for i in range(10)]) # 生成器表达式 # 特点: # 括号不一样 # 返回值不一样,几乎不占内存 # g = (i for i in range(10)) #用() # print(g) # for i in g: # print(i) # 老母鸡生成器,给蛋不如给老母鸡 # 老母鸡 = ('鸡蛋%s'%i for i in range(10)) # print(老母鸡) # for 蛋 in 老母鸡: # print(蛋) # g = (i*i for i in range(10)) #未执行时与函数定义一样,什么都不做 # print(g) # for i in g: # print(i) # 列表推导式 # 例一:30以内所有能被3整除的数 # print([i for i in range(31) if i%3==0]) # 例二:30以内所有能被3整除的数的平方 # print([i**2 for i in range(31) if i%3==0]) # 例三:找到嵌套列表中名字含有两个‘e’的所有名字 # names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'], # ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']] # print([name for lis in names for name in lis if name.count('e')>=2]) # 字典推导式 # 例一:将一个字典的key和value对调 # mcase = {'a': 10, 'b': 34} # mcase_frequency = {mcase[k]: k for k in mcase} # print(mcase_frequency) # 例二:合并大小写对应的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) # 集合推导式 # 例:计算列表中每个值的平方,自带去重功能 # print({i*i for i in [1,-1,3]}) # 可迭代对象: # 拥有__iter__方法 # 特点:惰性运算 #例如: range(), str, list, tuple, dict, set # 迭代器Iterator: # 拥有__iter__方法和__next__方法 # 例如: iter(range()), iter(str), iter(list), iter(tuple), iter(dict), iter(set), reversed(list_o), map(func, list_o), filter( # func, list_o), file_o # 生成器Generator: # 本质:迭代器,所以拥有__iter__方法和__next__方法 # 特点:惰性运算, 开发者自定义 # 使用生成器的优点: # 1. # 延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。