# # 迭代器和生成器
#
# # 迭代器:
# 双下方法:很少直接调用的方法。一般情况下,是通过其他语法触发
# 可迭代的——可迭代协议 含有__iter__的方法 '__iter__' in dir(数据)
# 可迭代的一定可以被for循环
# 迭代器协议:含有__iter__和__next__方法
# 迭代器一定可迭代,可迭代的通过调用iter()方法就能得到一个迭代器
#
# 迭代器的特点:
# 方便使用,且只能取所有的数据取一次
# 节省内存空间
#
# 生成器
# 生成器的本质就是迭代器
# 生成器的表现形式
# 生成器函数
# 生成器表达式
# 生成器函数:
# 含有yield关键字的函数就是生成器函数
# 特点:
# 调用函数的的之后函数不执行,返回一个生成器
# 调用next方法的时候回取到一个值
# 知道去完最后一个之后,在执行next会报错
# def generator():
# for i in range(2000000):
# yield i
#
# ret = generator() # 调用生成器函数得到一个生成器
# # print(list(ret))#数据类型强制转换,非常占据内存
# print(ret.__next__()) # 每一次执行ret.__next__(),就是从生成器中取值,预示着生成器函数中的代码继续执行
#
# for i in ret:
# if i>50:
# break
# print(i)
# i += 1
#
# 从生成器中取值的几个方法:
# next
# for循环
# 数据类型的强制转换:ret = generator() print(list(ret)) 不够好,占内存
# 生成器函数进阶
# def generator():
# print(123)
# yield 1
# print(456)
# yield 2
# print(789)
#
# ret = generator()
# ret.__next__() # 123
# ret.__next__() # 456
# ret.__next__() # 输出789,但是报错StopIteration
#
# def generator():
# print(123)
# content= yield 1
# print('****'+content)
# print(456)
# yield 2
#
# ret = generator()
# ret.__next__()
# ret.send('hello') # send的效果和next一样
#
# send 的获取下一个值得效果和next基本一致
# 只是在获取下一个值得时候,给上一个yield得位置传递一个数据
# 使用send的注意事项
# 第一次不能使用send
# 第一次使用生成器的时候,是用next获取下一个值
# 最后一个yield不能接受外部的值
# 计算移动平均值的例子:
# def average():
# sum = 0
# count= 0
# avg = 0
# while True:
# # num = yield
# num = yield avg
# sum += num
# count += 1
# avg = sum/count
#
# ret = average()
# ret.__next__()
# print(ret.send(10))
# print(ret.send(2))
# # 预激生成器的装饰器例子
# def init(f):
# def inner(*args,**kwargs):
# g = f(*args,**kwargs)
# g.__next__()
# return g
# return inner
#
# @init
# def average():
# sum = 0
# count= 0
# avg = 0
# while True:
# # num = yield
# num = yield avg
# sum += num
# count += 1
# avg = sum/count
#
# ret = average()
# print(ret.send(10))
# print(ret.send(30))
# def generator():
# a = 'abcde'
# b = '12345'
# # for i in a:
# # yield i
# # for j in b:
# # yield j
# yield from a
# yield from b
#
# ret = generator()
# for i in ret:
# print(i)
# 列表推导式和生成器表达式
# egg_list = ['egg%s'%i for i in range(10)]
# test1 = [i*2 for i in range(10)]
# print(test1)
# 生成器表达式
# g = (i for i in range(10))
# print(g) # <generator object <genexpr> at 0x10410d0f8>
# 同列表推导式不同点:括号不一样,返回值不一样,几乎不占用内容
# egg_g = ('egg%s'%i for i in range(10))
# print(egg_g)
# for i in egg_g:
# print(i)
#
# g1 = (i*i for i in range(10))
# print(g1)
# 各种推导式 # 遍历之后处理
# [满足条件的元素相关的操作 for 元素 in 可迭代数据类型 if 元素相关的条件] # 筛选功能
# # 30以内所有能被3整除的数
# ret = [i for i in range(30) if i%3 == 0] # 完整的列表推导式
# print(ret)
#
# # 30以内所有能被3整除的数的平方
# ret = [i*i for i in range(30) if i%3 == 0] # 完整的列表推导式
# print(ret)
# # 找嵌套列表中含有2个e的数
# lst = ['231e',['34ee','eerrte','ewtrew'],'werwe']
# ret = [name for lst1 in lst for name in lst1 if name.count('e')==2]
# print(ret)
# 字典推导式:key必须是可hash数值
# # 将一个字典的key和value值对调
# dct = {'a':1,'b':2}
# ret = {dct[key]:key for key in dct}
# print(ret)
#
# # 合并大小写对应的value值,将可以统一成小写
# dct = {'a':1,'b':2,'A':7,'B':9,'Z':3}
# ret = {key.lower():dct.get(key.lower(),0)+dct.get(key.upper(),0) for key in dct.keys()}
# print(ret)
# # 集合推导式{},集合自带去重功能
# # 计算列表中每个中的平方,自带去重功能
# test = {x**2 for x in [1,-1,2]}
# print(test)
# 各种推导式:生成器 列表、字典、集合
# 变量操作
# 筛选操作
# Eva_J
# 生成器中的数据只能取1次,取完就没了
# 惰性运算,不找它取值,就不工作
# homework
# # 1、处理文件,用户指定要查找的文件和内容,将文件正包含要查找内容每一行都输出到屏幕上
# def output_file_result(file,content):
# with open(file=file,mode='r',encoding='UTF-8') as f:
# for line in f:
# if content in line:
# print(line.strip())
# output_file_result('file','python')
# 2、写生成器,从文件中读取内容,在每一次读取到的内容之前加上'***'之后再返给用户
# def output_file_result_g():
# with open(file='file',mode='r',encoding='UTF-8') as f:
# for line in f:
# yield '***'+line.strip()
# ret = output_file_result_g()
# for i in ret:
# print(i)