迭代器与生成器

一、迭代器

L=[1,,2,3,4,5,]
  取值:索引、循环for
  循环for的取值:list列表 dic字典 str字符串 tuple元组 set f=open()句柄 range() enumerate枚举
  for i in L:

告诉我列表所拥有的所有方法

print(dir[])

判断某一数据类型是否有 __iter__ 方法(是否可迭代)

print('__iter__' in dir(int))
print('__iter__' in dir(bool))
print('__iter__' in dir(list))
print('__iter__' in dir(dict))
print('__iter__' in dir(set))
print('__iter__' in dir(tuple))
print('__iter__' in dir(enumerate([])))
print('__iter__' in dir(range(1)))    

只要能被 for 循环的数据类型,都有 _iter_ 方法

print([].__iter__())

一个列表执行了 __iter__() 之后的返回值就是一个迭代器

print(dir([]))
print(dir([].__iter__()))
print(set(dir([].__iter__())) - set(dir([])))
print([1,'a','bbb'].__iter__().__length_hint__())  #元素个数
l = [1,2,3]
iterator = l.__iter__()
print(iterator.__next__())
print(iterator.__next__())
print(iterator.__next__())
print(iterator.__next__())

迭代器的概念:
  内部含有 _next_ 方法和 _iter_ 方法的就是迭代器

可迭代协议:只要含有 _iter_ 方法的就是可迭代的
迭代器协议:内部含有 _next_ 方法和 _iter_ 方法的就是迭代器

可以被 for 循环的都是可迭代的

可迭代的内部都有 _iter_ 方法

Iterable 可迭代的
        _iter_--->只要含有_iter_方法的,都是可迭代的,都可以被for循环
[]._iter_() 迭代器
        _next_--->通过next方法就可以从迭代器一个一个取值    

for 循环其实就是在使用迭代器

iterator
可迭代对象
直接给你内存地址

关于 for 循环

只有是可迭代对象的时候,才能用for循环
当我们遇到一个新的变量,不能确定能不能循环的时候,判断他是否可迭代
print(_iter _ in dir([]))
print(_iter _ in dir(int))

迭代器的好处:

  • 1. 从容器类型中一个一个的取值,会把所有的值取到。
  • 2. 可以节省内存空间
  • 3. 迭代器不会在内存中再占用一大块内存,而是随着循环,每次生成一个,每次 next,每次给我一个
  • 4. 方便使用,且每个迭代器只能全部取一次

二、生成器:—- 迭代器

生成器函数:—- 本质上是自己写的函数

生成器函数:只要含有 yield 关键字的函数都是生成器函数
      yield 只能写在函数内部,不能和 return 共用

# 生成器函数
def generator():
    print(1)
    yield 'a'
                
ret = generator()
print(ret)

生成器函数的特点:

1.调用函数的之后函数不执行,返回一个生成器

def generator():
    print(1)
    return 'a'

ret = generator()
print(ret)

2.每调用一次__next__方法会取到一个值


def generator():
    print(1)
    yield 'a'
    print(2)
    yield 'b'
    yield 'c'

g = generator()
ret = g.__next__()
print(ret)
ret = g.__next__()
print(ret)
ret = g.__next__()
print(ret)

__next__方法
 3.直到取完最后一个,在执行next会报错


# 用for循环取值
打印2000000000个哇哈哈

def wahaha():
   for i in range(2000000):
       yield '娃哈哈%s' % i

生成器函数


g = wahaha()

调用生成器函数得到一个生成器


print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())

每调用一次__next__方法会取到一个值


g = wahaha()
count = 0
for i in g:
   count +=1
   print(i)
   if count > 50:
       break

从生成器中取值的几个方法


*  1.每调用一次__next__方法会取到一个值
*  2.用for循环批量取值 
*  3.数据类型的强制转换

监听文件输入例子

#文件监听,特定字符打印

def tail(filename):
    f = open(filename, encoding='utf-8')
    while True:
        line = f.readline()
        if line.strip():
            yield line.strip()


g = tail('file')
for i in g:
    if 'python' in i:
        print('***', i)