python_迭代器、生成器
# 迭代器
'''
被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)