python迭代器

一、迭代对象

1.1、可迭代对象

从语法形式上讲;可迭代对象就是内置有.__iter__方法的对象都是可迭代对象,其中字符串,列表,字典,元组,集合,以及打开的文件都是可迭代对象

二、迭代器对象

2.1、迭代器介绍

迭代器即用来迭代取值的工具,而迭代是重复反馈过程的活动,其目的通常是为了逼近所需的目标或结果,每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值,单纯的重复并不是迭代

通过索引的方式进行迭代取值,实现简单,但仅适用于序列类型:字符串,列表,元组。对于没有索引的字典(字典是按照key取值)、集合(主要用来去重和运算)等非序列类型,必须找到一种不依赖索引来进行迭代取值的方式,这就用到了迭代器。

2.2、迭代器对象

调用obj.iter()方法返回的结果就是一个迭代器对象(Iterator)。迭代器对象是内置有iter和next方法的对象,打开的文件本身就是一个迭代器对象,执行迭代器对象.iter()方法得到的仍然是迭代器本身,而执行迭代器.next()方法就会计算出迭代器中的下一个值。 迭代器是Python提供的一种统一的、不依赖于索引的迭代取值方式,只要存在多个“值”,无论序列类型还是非序列类型都可以按照迭代器的方式取值

简单的说,就是'''可迭代对象调用__iter__方法之后就是迭代器对象了''',而是否是可迭代对象是由数据的类型决定的

2.3、易错知识总结

1、可迭代对象多次调用___iter__方法仍然是迭代器对象,

2、res=s.__iter__() # 迭代器对象
    print(res.__next__())  # next其实就是迭代取值的,而且不依赖于索引取值

3、

l = [1, 2, 3, 4]
print(l.__iter__().__next__()) # 1
print(l.__iter__().__next__()) # 1
print(l.__iter__().__next__()) # 1
print(l.__iter__().__next__()) # 1

因为每次都是将可迭代对象l转换为迭代器对象然后取值,next一次就取一个值,因此每次结果为1

res = l.__iter__()
print(res.__next__())  # 1
print(res.__next__())  # 2
print(res.__next__())  # 3
print(res.__next__())  # 4  

先将可迭代对象转换为迭代器对象,然后每次next就是迭代取一次值,所以结果分别为1234

三、异常捕捉

3.1、什么是异常:

 异常就是错误发生的信号,如果不对该信号做处理,那么,异常发生的位置之后的代码都不能正常运行

"""
只能当你的被监测代码可能会出现,但是,又不想让它报错,这个时候使用异常捕捉是最合适的
异常捕捉的代码尽量少的写

"""   

 3.2、异常的信息:


 1. Traceback:追踪信息,异常发生的位置

有时候错误发生的信息可能会有很多行,你就找最后一行,然后点击可以跳转到错误发生的位置
 2. XXXError: 异常发生的类型

     NameError  KeyError  ...

3. 错误发生的详细信息(最重要的:一般情况从这里就可以知道异常发生的原因)
        name 'x' is not defined
        
 

3.3、异常的分类:


    1. 语法错误
        # 是代码运行过程中一开始就不允许的,只要语法错误,代码一定是不能够运行的
        # 通过代码提示就知道语法错误的原因
    2. 逻辑错误
        # 在编码过程中,逻辑错误是允许出现的
        但是我们应该尽量避免逻辑错误出现的可能性
       
            

3.4、异常如何进行捕捉

异常处理的基本形式:

方式一:

try:
    被检测的代码块
except 异常类型:
    检测到异常,就执行这个位置的逻辑

方式二:

如果我们想分别用不同的逻辑处理,需要用到多分支的except(类似于多分支的elif,从上到下依次匹配,匹配成功一次便不再匹配其他)

try:
    被检测的代码块
except NameError:
    触发NameError时对应的处理逻辑
except IndexError:
    触发IndexError时对应的处理逻辑
except KeyError:
    触发KeyError时对应的处理逻辑

方式三:

如果我们想多种类型的异常统一用一种逻辑处理,可以将多个异常放到一个元组内,用一个except匹配

try:
    被检测的代码块
except (NameError,IndexError,TypeError):
    触发NameError或IndexError或TypeError时对应的处理逻辑

方式四:

如果我们想捕获所有异常并用一种逻辑处理,Python提供了一个万能异常类型Exception

try:
    被检测的代码块
except Exception:
    所有类型的异常统一用此处的逻辑处理

方式五:

try还可以与finally连用,从语法上讲finally必须放到else之后,但可以使用try-except-finally的形式,也可以直接使用try-finally的形式。无论被检测的代码块是否触发异常,都会执行finally的子代码块,因此通常在finally的子代码块做一些回收资源的操作,比如关闭打开的文件、关闭数据库连接等

try:
   被检测的代码块
except 异常类型1:
   pass
except 异常类型2:
   pass
......
else:
   没有异常发生时执行的代码块
finally:
   无论有无异常发生都会执行的代码块

四、for循环的原理

for循环又称为迭代循环,in后跟的为任意可迭代对象,for循环工作的时候,会先调用iter方法,将可迭代对象转化为迭代器对象,然后在调用该迭代器对象的next方法,将取到的值一个一个赋值给for后边的变量名,直到将可迭代对象内的值取完,捕捉到StopIteration异常,结束迭代。

代码逻辑如下:

goods=['mac','lenovo','acer','dell','sony']
i=iter(goods) #每次都需要重新获取一个迭代器对象
while True:
    try:
        print(next(i))
    except StopIteration: #捕捉异常终止循环
        break

五、迭代器的优缺点

基于索引的迭代取值,所有迭代的状态都保存在了索引中,而基于迭代器实现迭代的方式不再需要索引,所有迭代的状态就保存在迭代器中,然而这种处理方式优点与缺点并存:

5.1 优点:

1、为序列和非序列类型提供了一种统一的迭代取值方式。

2、惰性计算:迭代器对象表示的是一个数据流,可以只在需要时才去调用next来计算出一个值,就迭代器本身来说,同一时刻在内存中只有一个值,因而可以存放无限大的数据流,而对于其他容器类型,如列表,需要把所有的元素都存放于内存中,受内存大小的限制,可以存放的值的个数是有限的。

5.2 缺点:

1、除非取尽,否则无法获取迭代器的长度

2、只能取下一个值,不能回到开始,更像是‘一次性的’,迭代器产生后的唯一目标就是重复执行next方法直到值取尽,否则就会停留在某个位置,等待下一次调用next;若是要再次迭代同个对象,你只能重新调用iter方法去创建一个新的迭代器对象,如果有两个或者多个循环使用同一个迭代器,必然只会有一个循环能取到值,原因如下:

在Python中,迭代器(iterator)是一个可以记住遍历的位置的对象。迭代器从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

当你使用同一个迭代器在多个循环中时,迭代器的状态(即当前位置)会在每个循环中被改变。由于迭代器只能前进,并且一旦所有元素被遍历后就会耗尽,所以如果一个迭代器已经在之前的循环中被完全遍历,那么后续的循环将无法从中获取任何值。举个例子:

my_list = [1, 2, 3]  
my_iterator = iter(my_list)  
  
# 第一个循环  
for item in my_iterator:  
    print(item)  # 输出: 1, 2, 3  
  
# 第二个循环尝试使用同一个迭代器  
for item in my_iterator:  
    print(item)  # 不会有输出,因为迭代器已经耗尽

在上面的例子中,第一个循环遍历了整个列表,并将迭代器移动到了列表的末尾。当第二个循环尝试使用时,迭代器已经耗尽,因此没有输出。

如果你希望多个循环能够遍历同一个集合,你应该为每个循环创建新的迭代器。例如,可以通过重新调用iter()函数或创建集合的新副本(如列表的切片)来实现这一点。

my_list = [1, 2, 3]  
  
# 为每个循环创建新的迭代器  
for item in iter(my_list):  
    print(item)  # 输出: 1, 2, 3  
  
for item in iter(my_list):  
    print(item)  # 再次输出: 1, 2, 3  
  
# 或者使用列表的切片来创建新的可迭代对象  
for item in my_list[:]:  
    print(item)  # 输出: 1, 2, 3  
  
for item in my_list[:]:  
    print(item)  # 再次输出: 1, 2, 3

注意,对于大型集合或性能敏感的代码,每次都创建新的迭代器或副本可能会带来额外的开销。在这种情况下,应该仔细考虑你的需求,并可能寻找其他解决方案,比如使用生成器函数来按需生成值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值