Python学习之路---迭代器和生成器

迭代器

能被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)

猜你喜欢

转载自blog.csdn.net/chengyinman0078/article/details/86763705