# 迭代器
'''
被for循环的数据
list
dict
str
set
tuple
f = open()
range()
enumerate
'''
# print(dir([])) # 告诉我列表拥有的所有方法
# 双下划线方法:很少直接调用的方法,一般情况下,是通过其他语法触发的
# 只要是能被for循环的数据类型 就一定拥有 __iter__ 方法
# [].__iter__():迭代器 --> __next__ # 通过next就可以从迭代器中一个一个的取值
from collections import Iterable # 可迭代的
from collections import Iterator # 迭代器
print(isinstance([],Iterable)) #判断 [] 是不是Iterable的关系
print(isinstance([],Iterator))
#迭代器概念
# 迭代器协议和可迭代协议
# 迭代器协议 : 内部含有 __next__ 和 __iter__方法的就是迭代器
# 可以被for循环的都是可迭代的
# 可迭代的内部都有 __iter__ 方法,可迭代协议:只要含有 __iter__ 方法都是可迭代的 ('__iter__' in dir(数据))
# 只要是迭代器 一定可迭代
# 可迭代的__iter__() 方法就可以得到一个迭代器
# 迭代器中的 __next__() 方法可以一个一个的获取值
# 迭代器的特点
# 很方便使用,且只能取所有的数据取一次
# 节省内存空间
# 生成器
# 生成器的本质就是迭代器
# 生成器的表现形式
# 生成器函数
# 生成器表达式
# 生成器函数:含有yield关键字的函数就是生成器函数
# 调用函数的之后函数不执行,返回一个生成器
# 调用next方法的时候会取到一个值
# 直到取完最后一个,在执行next会报错
def generator():
for i in range(20000):
yield '你想要的%s'%i
g = generator() # 调用生成器函数得到一个生成器
ret = g.__next__() # 每一次执行g.__next__ 就是从生成器中取值,预示着生成器函数中的代码继续执行
num = 0
for i in g:
num += 1
if num > 50:
break
print(i)
# 从生成器中取值的几个方法
# next
# for
# 数据类型的强制转换 :占用内存
readline 一行一行读
read(10)
# 在读出来的内容前面加上一个'****',再返回给调用着
def generator():
print(123)
content = yield 1
print(content)
print(456)
yield 2
g = generator()
ret = g.__next__()
print(ret)
ret = g.send('hello')
print(ret)
# send获取下一个值得效果和next基本一致,只是在获取下一个值时候,给上一个值yiled得位置传递一个数据
# 使用send注意事项
# 第一次使用生成器的时候 是用next获取下一个值
# 最后一个 yield 不能接受外部的值
#获取移动平均值
def init(func):
def inner(*args,**kwargs):
rg = func(*args,**kwargs) # g = average()
rg.__next__()
return rg
return inner
@init
def average():
sum = 0
count = 0
avg = 0
while True:
num = yield avg
sum += num
count += 1
avg = sum/count
rg = average()
ret = rg.send(10)
print(ret)
# yield from
def gen():
a = 'asdfg'
b = '12345'
yield from a # 能够一个一个取a的值
yield from b
g = gen()
for i in g:
print(i)