首页 > 其他分享 >day5可迭代对象与迭代器和生成器

day5可迭代对象与迭代器和生成器

时间:2022-10-26 15:11:47浏览次数:54  
标签:__ .__ 迭代 生成器 iter next print day

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

相关文章

  • day18 批量查询与模糊查询 & 聚合函数与内置函数 & distinct关键字 & 分页查询limit &
    day18两个表student和userstudentids_names_ages_sexuseridu_nameu_ageu_sex批量插入insertintostudents_names_sexselectu_name,u_sexfromuser;//......
  • 代码随想录day21 | 530.二叉搜索树的最小绝对差 501. 二叉搜索树中的众数 236. 二叉
    530.二叉搜索树的最小绝对差题目|文章思路二叉搜索树的特点是按照中序遍历从小到大进行排列,因此,按照中序遍历,逐个比较即可找到最小差值进行中序遍历,当前节点和前一个......
  • day4.2
    基本数据的运算boolean不参与转换,其余7个(byte,short,char,int,long,folat,double)可以互相转换低转高,可以自动转换。高转低,需要强制转换,同时会存在丢失精度的风险。byte,char,s......
  • Day4.1
    运算符算术运算符+,-,*,/,%,++,--;关系运算符,<,<=,>=,==,!=;逻辑运算符&&,||,!赋值运算符=,+=,-=,*=,/=,%=,^=,&=,|=,<<=,>>=;(**使用扩展运算符时,永远不会改变运算结果类型)位运算符&,|,^,~,>>......
  • day19 原型和继承
    面对对象回顾通过new构造函数的方法class的constructor(es6)classPerson{constructor(name,age){//构造器this.name=name}}varperson......
  • 学习python-Day79
    昨日内容回顾前端发展历史vue react谷歌flutter,Dart语言uni-app:小公司vue:3.x2.x3.x====>ts2.x====>jsvue渐进式MVVMM层:model,数据层,jsV层:view,视......
  • Day4:Python基础:元祖方法一
    1、元祖打印Tu=(1,2,3,'Alex',[2,3,4,'taibai'],'egon')print(Tu[3])2、元祖字符转大写Tu=(1,2,3,'Alex',[2,3,4,'taibai'],'egon')Tu[4][3]=Tu[4][3].upp......
  • day53-马踏棋盘
    马踏棋盘1.算法优化的意义算法是程序的灵魂,为什么有些程序可以在海量数据计算时,依旧保持高速计算?编程中算法很多,比如八大排序算法(冒泡、选择、插入、快排、归并、希尔......
  • day4.0
    javac转译出现问题:notepad++设置为UTF-8编写时,每次转译需要加上-encodingUTF-8,javac才能识别,设置成ansi时,javac能够正常识别中文(来回切换一下编码)byte-128~127;shor......
  • day11DOM和BOM回顾以及事件讲解 ( 上 )
    内容回顾BOM(bowserobjectmodel)浏览器对象模型window:窗口对象(全局的变量及函数都属于window也就是global全局对象)location:地址栏对象(获取地......