迭代器和生成器
一、迭代器 (概念)
1.可迭代协议--->:只要是含有’__iter__’方法的数据类型都是可迭代的数据类型
判断么某个变量是不是可迭代的:
第一种方式:
print('__iter__' in dir([])) #是True就是可迭代的,是False就不是.
第二种方式:
from collections import Iterable
isinstance([],Iterable)
内置函数,判断一个具体的值是不是某个数据类型,括号里前面是具体的值,后面是数据类型.
2.迭代器协议---->:内部含有''__next__''方法和__iter__方法的数据类型就是迭代器
判断一个数据是不是迭代器:
第一种:
print('__iter__' in dir(res.__iter__()) and '__next__' in dir(res.__iter__()))
第二种:
from collections import Iterator
r = isinstance(res,Iterator) #r为True即为真,为False即为假
可迭代的和迭代器的关系:所有的迭代器都是可迭代的,反之不成立
3.创建一个迭代器:
l = []
res = l.__iter__()
print(res)
4.查看在res中但是不在l中的方法的方法:
print(set(dir(res)) - set(dir(l)))
相对于可迭代的迭代器中特有的方法:
{'__length_hint__', '__next__', '__setstate__'}
res.__lenght_hint__() #跌迭代器中有多少的元素
res.__setstate__() #控制迭代器从哪个位置开始迭代
res.__next__() #从迭代器中取下一个值
5.迭代器的特点:
a.具有next和iter两种方法
b.通过一个__next__多次执行就可以获得这个容器数据类型的所有的值
c.迭代器中的值只能取一次 ,不取的时候值不出现 ###重点
6.用途:
a.for循环内部的循环机制就是迭代器的取值机制
b.在for循环执行的过程中,是先把可迭代数据变成迭代器,在从中一个个的取值
7.迭代器的优点:
a.range生成的就是一个迭代器,创建这个迭代器并不会把这个迭代器的数据一次性生成,只有通过next取值的时候才会生成
b.所有的for循环与一个这个过程:记住要多少个值,当前该给你什么并且记住下一个该给你什么和当前值和下一个数的关系即可
c.for循环就是利用迭代器节省内存的优点来处理数据中的变量
8.特点:
a.节省内存
b.惰性运算:记住要多少个值,当前该给你什么并且记住下一个该给你什么和当前值和下一个数的关系即可,可以节省时间
c.只能一次性取值,并且按顺序取
9.for循环和迭代器的关系:
无论是可迭代的还是迭代器都是可以被for循环的,如果是循环的迭代器,则循环一次就没了.如果循环的是费迭代器,每一次都相当于从头开始,因为在for循环中每一次循环都会通过__iter__生成一个新的迭代器
二、生成器
1.概念:通过简单的函数实现的
生成器函数: 如果一个函数中含有yield关键字,则该函数即返回一个生成器函数,所有的生成器都是一个迭代器
迭代器的取值方法都适用于生成器:
a..通过for循环
b.通过__next__()函数
c.使用数据类型的强制转换
2.send()函数:
1.send() 相当于执行一次__next__,并且在yield的时候输入一个值
2.生成器中send()使用的的过程:
a.生成器函数得到的是一个生成器
b启动生成器的第一个方法永远是next
c.从第二个开始,可以是send()c
d.g.next相当于一个g.send(None)
e.如果send()发送了值,但是没有接收,也不会报错
4.在我们的生成器函数中:
a.send / __next__ 在函数之外用的
b.yield / yield from 在函数之内使用的
c.next + send 的个数等于yield的个数
d.如果函数中的yield不需要接受参数,只需使用next
e.生成器和迭代器是一样的,内部的值只能取一次
5.示例程序:
a.监听文件的输入,对文件进行实时的分析:
def get_line():
f = open('1',encoding = 'utf-8')
while True :
line = f.readline().strip()
if line :
yield line.strip()
line_g = get_line()
for line in line_g:
print(line.split(','))
2.计算移动平均值的例子:
def cail_avg():
sum_n =0
count = 0
while True :
if count != 0:
num = yield sum_n / count
else:
num = yield 0
sum_n += num
count += 1
g = cail_avg()
print(g.__next__())
print(g.send(7))
print(g.send(8))
print(g.send(9))