# 迭代器
# 迭代器协议:对象必须提供一个next方法,执行该方法要么返回迭代的下一项,要么引起一个Stopiteration异常,以终止迭代(只能往后走不能往前退)
# 可迭代对象:实现了迭代器协议的对象(对象内部定义一个__iter__()方法)
# 协议是一种约定,可迭代对象实现了迭代器协议
# 字符串、列表、元组、字典、集合、文件对象等都不是可迭代对象,只不过在for循环,调用了他们内部的__iner__方法,把它们变成了可迭代对象
# python内部工具(for sum min max map reduce filter)等使用迭代器协议访问对象,和下标没有关系
x = 'hello'
x_iter = x.__iter__() # 将字符串转换为可迭代对象 或使用 iter(l)
print(x_iter.__next__()) # 此时就可以使用__next__方法
print(x_iter.__next__())
print(x_iter.__next__())
print(next(x_iter))
print(x_iter.__next__())
# 内置函数中的next()方法,实际上就是调用了对象内置的__next__()方法
# 对于字典、集合、文件对象等无序的对象是没有下标的,所以我们使用for来将其转换为可迭代对象对其迭代
# 只要能用for遍历的,全部都有__iter__方法
# 对于可迭代对象,只有需要取(__next__())的时候才会放到内存中,取到下一条时,上一条就从内存中销毁,这样节约内存
# iter的扩展
l = ['a', 'b', 'c', 'd']
def test():
return l.pop() # 将列表中最后一个元素pop出去
x = iter(test, 'b') # 将test函数转换成一个迭代器对象,并且当结果为b时StopIteration
print(x.__next__()) # d
print(x.__next__()) # c
print(x.__next__()) # StopIteration
# 生成器
# 一种数据类型,自动实现了迭代器协议,就是一个可迭代对象, 只能遍历一次
# 生成器的两种表现方式
# 1,生成器函数 函数中含yield,代替return,可以yield多次,使用next或__next__或send()来停到某个位置,用来保存状态
def test():
yield 1
g = test()
print(g)
print(g.__next__())
# print(g.__next__())
# 一个补充
# 三元表达式
name = 'alex'
res = 'sb' if name == 'alex' else '帅哥'
# if前边是为True时的值,else后边是为False时的值
print(res)
# 列表解析(使用三元表达式方式),但是生成的列表会将所有数据放入内存中
egg_list = []
for i in range(10):
egg_list.append('鸡蛋%s' % i)
print(egg_list)
# 以上方式等同于以下
l = ['鸡蛋%s' % i for i in range(10)]
print(l)
# 引申的案例,只把鸡蛋大于5的放入篮子中
l = ['鸡蛋%s' % i for i in range(10) if i > 5]
# 2,生成器表达式
# 生成器表达式对应上面的案例,只需要把列表的[]换成()
l = ('鸡蛋%s' % i for i in range(10))
print(l)
print(l.__next__())
print(l.__next__())
print(l.__next__())
print(l.__next__())
print(l.__next__())
print(next(l))
# 补充 sum 对生成器进行计算,这样不会将这么大的数字全放在内存中,造成电脑崩溃
print(sum(i for i in range(1000000000000000)))