day5.可迭代对象与迭代器和生成器
1.迭代器的基本概念
1.1.什么是迭代器
迭代就是更新换代
1.1. 迭代器指的是迭代取值的工具
1.2. 迭代是一个重复的过程,每一次重复都是基于上一次的结果而来
比如:爹生了儿子,儿子生了孙子
1.第一次开发的项目,互联网公司
前面实现基本功能,保证用户量
后面可以慢慢改,提升品质
2.老师第一次上课,紧张,技术难点,第一次不可能
讲的完美,但是慢慢提升,如果存在问题同学们可以指出,
也是一个迭代的过程。
3.学习也是一个迭代的过程,它是基于上次学习的结果的
一次理解了60%,下次看看变成80%,运用了100%。
4.第一次恋爱,也不可能完美,也是慢慢提升的过程
1.2.为何要用迭代器
器是工具
迭代器提供了一种通用的且不依赖于索引的迭代取值方式的功能
2.如何用迭代器
2.1.迭代取值
#单纯的重复不是迭代
i = 0
while True:
print(i)
# 1.2. 迭代是一重复的过程,每一次重复都是基于上一次的结果而来
l = ['a','b','c']
# # # # 0 1 2
i = 0
while i< len(l):
# print(i)
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(t):
# print(i)
print(t[i])
i += 1
# 所以我们需要一种不依赖索引取值的方式
# 迭代器提供了一种通用的且不依赖于索引的迭代取值方式的功能
2.2.可迭代对象
# 可迭代对象
#一 :可迭代的对象iterable:但凡内置有__iter__方法的对象都称之为可迭代的对象
# 因为__iter__方法这个方法可以生成迭代器
# 作者是个天才,每个需要取值的都加了__iter__方法
a = 1
# a.__iter__没有
b = 1.1
# # b.__iter__没有
c = 'hello'
# c.__iter__()
d = ['a','c']
# d.__iter__()
g = {1,2,3}
# g.__iter__()
f = open('c.txt','rt')
# f.__iter__()
2.3.迭代器
# 迭代器
# 执行可迭代对象下的__iter__方法,返回的值就是一个迭代器
# dic是可迭代对象
dic = {'x':1,'y':2,'z':3}
# # # # # # 可迭代对象变成迭代器
iter_dic=dic.__iter__()
print(iter_dic)
# # # # 迭代器 range 母鸡
print(iter_dic.__next__())
print(iter_dic.__next__())
print(iter_dic.__next__())
# # # # # #StopIteration应该被当成一种结束信号,代表迭代器取干净了
# print(iter_dic.__next__())
# 列表不依赖索引取值
l = [1,2,3]
iter_l = l.__iter__()
# # print(iter_l)
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
# # # # # # #StopIteration应该被当成一种结束信号,代表迭代器取干净了
# print(iter_l.__next__())
# 误区
l = [1,2,3]
# 基于新的迭代器 l.__iter__()
# # 生成了一个迭代器,并且取了第一个值
print(l.__iter__().__next__())# 1
# # 又生成了一个迭代器,并且取了第一个值
print(l.__iter__().__next__())
# # 又生成了一个迭代器,并且取了第一个值
print(l.__iter__().__next__())
# # # # # 迭代是基于老的
iter_l = l.__iter__()
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
# # StopIteration应该被当成一种结束信号,代表迭代器取干净了
# print(iter_l.__next__())
2.4.可迭代对象与迭代器
# 作者是个天才,每个需要取值的都加了__iter__方法,可以变成迭代器,还有些直接就是迭代器,比如文件
a = 1
# a.__iter__没有
b = 1.1
# # b.__iter__没有
c = 'hello'
# c.__iter__()
# # c.__next__()没有
d = ['a','c']
# d.__iter__()
# # d.__next__没有
g = {1,2,3}
# g.__iter__()
# g.__next__没有
f = open('c.txt','rt')
f.__iter__()
f.__next__()
# 可迭代对象与迭代器 *****
# 可迭代对象
# 只有__iter__方法,没有__next__方法
# 迭代器
#1. 既内置有__next__方法的对象,执行迭代器__next__方法可以不依赖索引取值
#2. 又内置有__iter__方法的对象,执行迭代器__iter__方法得到的仍然是迭代器本身
# 1 迭代器一定是可迭代的对象,而可迭代的对象却不一定是迭代器
# 可迭代的对象只需要有__iter__()
# 迭代器对象 __iter__() __next__()
f = open('c.txt','rt')
# f是迭代器
print(f)
print(f.__next__(),end='')
print(f.__next__())
# # StopIteration应该被当成一种结束信号,代表迭代器取干净了
# print(f.__next__())
# # # # 调用可迭代的对象__iter__得到的是迭代器,
# # # # 执行迭代器__iter__方法得到的仍然是迭代器本身,那么有什么用
print(f.__iter__() is f.__iter__().__iter__().__iter__().__iter__())
2.5.迭代器为什么和for循环使用
# # 为了for循环
# iter() next()
dic = {'x':1,'y':2,'z':3}
# # # # 可迭代对象生成迭代器
# # # # 底层
iter_dic = dic.__iter__()
print(iter_dic)
iter_dic = iter(dic)
print(iter_dic)
# # # 内置方法
print(next(iter_dic))
print(next(iter_dic))
print(next(iter_dic))
# # StopIteration应该被当成一种结束信号,代表迭代器取干净了
# print(next(iter_dic))
dic = {'x':1,'y':2,'z':3}
iter_dic1=iter(dic)
while True:
try:
print(next(iter_dic1))
except StopIteration:
break
print('=================')
while True:
try:
print(next(iter_dic1))
except StopIteration:
break
# 有没有一种好的方法自己把
# 1.可迭代对象变成迭代器
# 2.能够自己获取迭代器next的值
# 3.next最后不报错
#for本质应该称之为迭代器循环
# 生成一个迭代器
l = [1,2,3]
iter_l = l.__iter__()
print(iter_l)
# # # # # 调用可迭代的对象__iter__得到的是迭代器,
# # # # # 执行迭代器__iter__方法得到的仍然是迭代器本身,那么有什么用
print(f.__iter__() is f.__iter__().__iter__().__iter__().__iter__())
# # 为了for循环
#1. 先调用in后面那个对象的__iter__方法,将其变成一个迭代器
# 如果是个迭代器__iter__可以变成迭代器 老的迭代器
# # 如果是个可迭代对象__iter__可以变成迭代器 新的迭代器
#2. 调用next(迭代器),将得到的返回值赋值给变量名 k
#3. 循环往复直到next(迭代器)抛出异常,for会自动捕捉异常StopIteration然后结束循环
l= [1,2,3]
for k in l:
print(k)
# # # # # # 为什么下一次又可以
# # # # # # 因为又做了上面三件事 又变成了一个新的迭代器
for k in l:
print(k)
f = open('c.txt','rt')
print(f is f.__iter__())
for line in f:
print(line,end='')
2.6.迭代器总结
#迭代器总结
# 优点:
# 1. 提供一种通用的且不依赖于索引的迭代取值方式
# 2. 同一时刻在内存中只存在一个值,更节省内存
# 缺点:
# 1. 取值不如按照索引的方式灵活,(不能取指定的某一个值,而且只能往后取)
# 2. 无法预测迭代器的长度
# 还记得range吗
obj_iter = range(1,10)
print(obj_iter)
# obj_iter可迭代对象
obj_next=obj_iter.__iter__()
# obj_next就是迭代器
# print(obj_next)
print(obj_next.__next__())
print(obj_next.__next__())
print(obj_next.__next__())
# i 1 4
# 同一个迭代器
print('迭代器的for循环下了三个鸡蛋的母鸡')
for i in obj_next:
print(i)
print('再次')
for i in obj_next:
print(i)
print('可迭代对象的for循环没下蛋的母鸡')
for i in obj_iter:
print(i)
print('可迭代对象的for循环2没下蛋的母鸡')
for i in obj_iter:
print(i)
# # obj_iter可迭代对象是会生成新的迭代器
# # obj_next迭代器是基于老的迭代器取值
3.生成器
大前提:生成器就是一种自定义的迭代器,本质就是迭代器
3.1.生成器的使用
但凡函数内包含yield关键字,调用函数不会执行函数体代码
会得到一个返回值,该返回值就是生成器对象
def func():
print('======1')
yield 1
print('======2')
yield 2
g=func()
print(g)
# # g.__iter__()
# # g.__next__()
# # print(g is g.__iter__().__iter__())
# # # # # #会触发函数的执行,直到碰到一个yield停下来,并且将yield后的值当作本次next的结果返回
res1=next(g)
print(res1)
res2=next(g)
print(res2)
3.2.生成器和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 第一是a 1 b 1 第二次 a 1 b 2 第三次 a 2 b 3 第四次 a 3 b 5 第五次 a 5 b 8
a , b = b ,a +b
i+=1
my_run=run(10)
# print(my_run)
print(list(my_run))
# for i in my_run:
# print(i)
3.3.生成器计算阶乘
# @Author : 大海
# @File : 3.生成器计算阶乘.py
'''
用生成器来计算1!+2!+3!+4!+......10!的和
'''
# 阶乘
# 1! = 1
# 2! = 2*1
# 3! = 3*2*1
# 4! = 4*3*2*1
# 计数变量i
def func(n):# n 的阶乘
i = 1 # 计数的变量 第一次 i 1
j = 1
while i <= n:
yield j # 第一次 j 1
i+=1# 计数自增1 第二次 i 2 第三次 i 3 第四次 i 4 第5 次 i 5
j = j * i # 第二次 j 2 第三次 j 1*2 * 3 = 6 第四次 j 1 *2 * 3 * 4 = 24 第5 次 1 *2 * 3 * 4 * 5
a=func(10)
print(a)
# s = 0
# for i in a:
# # print(i)
# s += i
# print(s)
print(sum(list(a)))
标签:__,.__,迭代,生成器,iter,next,print,day
From: https://www.cnblogs.com/shiruiyang/p/16825516.html