文章目录
迭代器
分清楚迭代与循环
偏理解
知道for循环后面跟什么 *****
生成器的作业
- 什么是迭代器
迭代就是更新换代
迭代器指的是迭代取值的工具- 为何要用迭代器
器是工具
迭代器提供了一种通用的且不依赖于索引的迭代取值方式的功能
### 迭代器的使用
#单纯的重复不是迭代
# i = 0
# while True:
# print(i)
# 迭代:重复+每次重复都是基于上一次的结果而进行(不是是单纯的重复)
# l = ['a','b','c']
# i = 0
# while i < len(l):
# print(l[i])
# i += 1
# # 哪些数据类型需要这样迭代取值
# # 字符串 列表 元组 字典 集合 文件等等
# l = ['a','b','c']
# a = 'abc'
# t = ('a','b','c')
# dic = {'name':'dahai','age':18}
# i = 0
# while i < len(l):
# print(l[i])
# i += 1
# 所以我们需要一种不依赖索引取值的方式
# 迭代器提供了一种通用的且不依赖于索引的迭代取值方式的功能
可迭代对象
# 可迭代对象
#一 :可迭代的对象iterable:但凡内置有__iter__方法的对象都称之为可迭代的对象
# 作者是个天才,每个需要取值的都加了__iter__方法
#可迭代的对象:str,list,tuple,dict,set,文件对象
a = 1
# a.__iter__没有
b = 1.1
# b.__iter__没有
c = 'hello'
print(c.__iter__())
d = ['a', 'c']
print(d.__iter__())
e = {'x': 1}
print(e.__iter__())
g = {1, 2, 3}
# g是可迭代对象
# g.__iter__()会生成迭代器
print(g.__iter__())
f = open('b.txt', 'w')
print(f.__iter__())
迭代器
# 迭代器
# 执行可迭代对象下的__iter__方法,返回的值就是一个迭代器对象
dic = {'x': 1, 'y': 2, 'z': 3}
# 迭代器对象变成迭代器
iter_dic = dic.__iter__()
# iter_dic迭代器
print(iter_dic.__next__())
print(iter_dic.__next__())
print(iter_dic.__next__())
# 列表不依赖索引取值
l = [1, 2, 3]
iter_l = l.__iter__()
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
# #StopIteration应该被当成一种结束信号,代表迭代器取干净了
print(iter_l.__next__())
# 误区
l = [1, 2, 3]
print(l.__iter__().__next__())
# 基于新的迭代器对象
print(l.__iter__().__next__())
# 迭代是基于老的
iter_l = l.__iter__()
print(iter_l.__next__())
print(iter_l.__next__())
可迭代对象与迭代器 *****
可迭代对象
只有__iter__方法,没有__next__方法
除了文件其他容器都是可迭代对象
迭代器
- 既内置有__next__方法的对象,执行迭代器__next__方法可以不依赖索引取值
- 又内置有__iter__方法的对象,执行迭代器__iter__方法得到的仍然是迭代器本身
迭代器一定是可迭代的对象,而可迭代的对象却不一定是迭代器对象
可迭代的对象只需要有__iter__()
迭代器对象 iter() next()
文件对象也是迭代器
f = open('b.txt', 'w')
print(f.__iter__())
l = [1, 2, 3]
iter_l = l.__iter__()
# 调用可迭代的对象__iter__得到的是迭代器,
# 执行迭代器__iter__方法得到的仍然是迭代器本身,那么有什么用
# 为了for循环
print(iter_l is iter_l.__iter__().__iter__().__iter__())
iter() next()
# iter() next()
dic = {'x': 1, 'y': 2, 'z': 3}
#
iter_dic = iter(dic)
print(iter_dic)
# 底层 print(dic.__iter__())
print(next(iter_dic))
# 底层 print(iter_dic.__next__())
# 解决迭代器报错
# 异常捕获
dic = {'x': 1, 'y': 2, 'z': 3}
#
iter_dic = iter(dic)
# 异常捕获
while True:
try:
print(next(iter_dic))
except StopIteration:
break
print('=========')
# # 同一个迭代器只能完整地取完一次值
while True:
try:
print(next(iter_dic))
except StopIteration:
break
for循环原理
# 有没有一种好的方法自己把
# 1.可迭代对象变成迭代器对象
# 2.能够自己获取迭代器对象next的值
# 3.next最后不报错
#for本质应该称之为迭代器循环 *****
# 那么以后大家知道for循环后面可以跟迭代器和可迭代对象
#底层工作原理
#1. 先调用in后面那个对象的__iter__方法,将其变成一个迭代器
# 如果是个迭代器__iter__可以变成迭代器
# 如果是个可迭代对象__iter__可以变成迭代器
#2. 调用next(迭代器),将得到的返回值赋值给变量名 k
#3. 循环往复直到next(迭代器)抛出异常,for会自动捕捉异常StopIteration然后结束循环
# 可迭代对象包含迭代器对象
# 文件对象是迭代器,那么for循环也会自动调用__iter__,那么还是一个迭代器
# 那么for循环的机制就可以通用,这就是为什么迭代器对象里面也有一个__iter__的方法的原因
dic = {'x': 1, 'y': 2, 'z': 3}
for k in dic:
print(k)
# 为什么下一次又可以
# 因为又做了上面三件事 又变成了一个新的dic迭代器
for k in dic:
print(k)
迭代器总结
#迭代器总结
# 优点:
# 1. 提供一种通用的且不依赖于索引的迭代取值方式
# 2. 同一时刻在内存中只存在一个值,更节省内存
# 缺点:
# 1. 取值不如按照索引的方式灵活,(不能取指定的某一个值,而且只能往后取)
# 2. 无法预测迭代器的长度
range函数原理
obj_iter = range(1, 10)
# obj_iter可迭代对象
print(obj_iter)
obj_next = iter(obj_iter)
print(obj_next.__next__())
print(obj_next.__next__())
print(obj_next.__next__())
print('迭代器的for循环') # 1 开 1 4
for i in obj_next:
print(i)
print('可迭代对象for循环')
print('=============')
for i in obj_iter:
print(i)
生成器
大前提:生成器就是一种自定义的迭代器,本质就是迭代器
但凡函数内包含yield关键字,调用函数不会执行函数体代码,
会得到一个返回值,该返回值就是生成器对象
def func():
print('====1')
yield 1
print('====2')
yield 2
print('====3')
yield 3
g = func()
print(g)
print(g is g.__iter__().__iter__())
g.__next__()
res1 = next(g)
# #会触发函数的执行,直到碰到一个yield停下来,并且将yield后的值当作本次next的结果返回
print(res1)
res2 = next(g)
print(res2)
res3 = next(g)
print(res3)
# 生成器一般for连用
# for i in g:
# print(i)
# 总结yield:只能在函数内使用
#1. yield提供了一种自定义迭代器的解决方案
#2. yield可以保存函数的暂停的状态
#3. yield对比return
# 1. 相同点:都可以返回值,值的类型与个数都没有限制
# 2. 不同点:yield可以返回多次值,而return只能返回一次值函数就结束了
生成一个斐波那契数列
'''
定义一个生成器,这个生成器可以生成10位斐波拉契数列,得到斐波拉契数列
# (斐波那契数列:数列中每一个数的值都等于前两个数相加的值 [1, 1, 2, 3, 5, 8, 13, 21, 34, 55.........])
'''
def run(n):
i, a, b = 0, 1, 1
while i < n:
yield a
a, b = b, a + b
i += 1
for i in run(10):
print(i)