迭代器
能被for循环的数据类型 list # 列表 dict # 字典 str # 字符 set # 集合 tuple # 元组 f = open() # 文件句柄 range() enumerate # 枚举
查看数据类型含有什么方法 使用dir()
print(dir([]))
双下方法:__方法名__()
print(dir([])) 查看方法 print('__add__' in dir([])) #判断双下方法__add__是否在列表方法内 print([1].__add__([2])) # 等同于print([1]+[2]) print([1] + [2]) # 实际运行的方法是print([1].__add__([2]))
可迭代对象:
只要数据类型含有__iter__方法的的数据类型都是可迭代对象
只要都能被for循环的都是可迭代对象
迭代器
当可迭代对象使用了__iter__方法后,它的返回值就是一个迭代器
只要是迭代器 一定可迭代
print(dir([])) print(dir([].__iter__()))
迭代器必须同时包含__iter__和__next__两个方法
__next__()方法可以一个一个的获取值 # for循环其实就是在使用迭代器
print(set(dir([].__iter__())) - set(dir([]))) # 例子 l = [1, 2, 3] print(l.__iter__().__next__()) # 将l 列表通过__iter__()转为迭代器,接着通过__next__可以取一个值 print(l.__iter__().__next__()) # 将l 列表通过__iter__()转为迭代器,接着通过__next__可以取下一个值 print(l.__iter__().__next__()) # 将l 列表通过__iter__()转为迭代器,接着通过__next__可以取下一个值 print(l.__iter__().__next__()) # 因列表已经没有第四个值,直接报错 # 模拟for循环 l = [1,2,3,4,5,6,7,8,9] a = iter(l) # 将l 转为为迭代器 print('__iter__'and '__next__' in dir(a)) while True: print(a.__next__())
可迭代协议:只要含有__iter__方法的都是可迭代的
迭代器协议:内部含有__iter__和__next__方法的迭代器
迭代器的好处:
1、从容器类型中一个一个的取值,会把所有的值都取到;
2、节省内存空间 :不会一次性产生所有值,仅通过循环或__next__(),一次取一个
print(range(100000000)) print(list(range(100000000)))
注意:迭代器很好,但是并不能解决所有的,比如我需要生成200W个不同的字符串,于是引出生成器
生成器
生成器的本质就是一个迭代器
生成器函数
1、只要含有yield关键字的函数都是生成器函数,只能用在函数内且不能和return同时存在
2、且执行完yield后这个函数不会结束,可以用__next__接着取值
3、调用函数的时候,函数体不执行,返回一个生成器
4、调用next方法的是会取到一个值,直到完全取完,再执行__next__()就会报错
def get(): for i in range(200): yield i ret = get() print(ret) print('__iter__'and '__next__' in dir(ret)) while True: print(ret.__next__()) #for i in ret: # print(i)
生成器函数的取值方式:
1、__next__()
2、for
3、数据类型的强制转换 list(ret) 占用内存
注意:因为yield关键字,返回值后函数并没有结束,所以可以接着往下用__next__()取值,直到报错
def generator(): print(1) yield 'a' print(2) yield 'b' print(3) yield 'c' g = generator() ret = g.__next__() print(ret) ret = g.__next__() print(ret) ret = g.__next__() print(ret) ret = g.__next__() # 会报错 因为只有3个yield print(ret) #for i in g: # print(i)
注意:解决---我需要生成200W个不同的字符串
def test(): for i in range(200): yield '第%s个 Hello'%i g = test() for i in g: print(i)
问题的进阶:仅需要前50个,接着取51个能否取到?
def test(): for i in range(200): yield '第%s个 Hello'%i g = test() count = 0 for i in g: count += 1 print(i) if count >50: break print(g.__next__())
注意:每对新的变量赋予一次生成器函数调用,不于之前的有任何关联
def test(): for i in range(200): yield '第%s个 Hello'%i g = test() g1 = test() count = 0 for i in g: count += 1 print(i) if count >50: break print(g.__next__()) print(g1.__next__())
例子:监听文件输入
# 注意文件里输入内容后,保存一下,不然不会实时输出 def genternor(filename): with open(filename,encoding='utf-8') as f : while True: line = f.readline().strip() if line: print(line) genternor('count')
问题进阶:如发现输入有Python,实时输出内容+‘******’,或者仅输出带Python的字符串
达到监听过滤的效果
def genternor(filename): with open(filename,encoding='utf-8') as f : while True: line = f.readline().strip() if line: yield line ret = genternor('count') for i in ret: if 'python' in i : print('*****',i) else: print(i) #仅打印带python的字符串 # for i in ret: # if 'python' in i : # print(i)