当前位置: 首页 > article >正文

来看看Python迭代器能让你的代码提升100倍的密码

在这里插入图片描述

  • 博客主页:长风清留扬-CSDN博客
  • 系列专栏:Python基础专栏
  • 每天更新大数据相关方面的技术,分享自己的实战工作经验和学习总结,尽量帮助大家解决更多问题和学习更多新知识,欢迎评论区分享自己的看法
  • 感谢大家点赞👍收藏⭐评论

一、迭代器

迭代器的定义

迭代器是一个实现了迭代器协议的对象。迭代器协议规定了一个对象必须实现两个方法:iter() 和 next()。然而,需要注意的是,从严格意义上讲,一个迭代器对象只需要实现 next() 方法,因为 iter() 函数(用于获取迭代器)会自动调用对象的 iter() 方法(如果该方法存在),而该方法通常返回对象自身。因此,在实际应用中,我们通常将只实现了 next() 方法的对象称为迭代器。

迭代器协议

迭代器协议是指迭代器对象必须遵循的一组规则

iter() 方法:

  • 返回迭代器对象本身。
  • 在Python中,如果一个对象实现了 iter() 方法,那么它就被认为是可迭代的(iterable)。
  • 但对于迭代器对象而言,iter() 方法通常只是简单地返回 self。

next() 方法:

  • 返回序列中的下一个元素。
  • 如果序列中没有更多元素可供返回,则该方法应该抛出 StopIteration 异常,以通知迭代器的使用者迭代已经完成。

迭代器的特点

  • 惰性求值:迭代器采用惰性求值的方式,即只有在需要时才生成值。这有助于节省内存,特别是在处理大型数据集或无限序列时。
  • 状态跟踪:迭代器内部维护了一个状态,用于跟踪当前迭代到的位置。这确保了每次调用 next() 方法时,都会返回序列中的下一个元素。
  • 单次遍历:迭代器只能向前移动,不能回退。一旦迭代器耗尽(即抛出 StopIteration 异常),它将无法再次使用来遍历序列。

迭代器的使用

在Python中,你可以通过调用对象的 iter() 方法(或更常见的是使用内置的 iter() 函数)来获取一个迭代器。然后,你可以使用 next() 函数(或在循环中直接使用迭代器)来逐个访问元素,直到捕获到 StopIteration 异常为止。

迭代器的优势

  • 节省内存:由于迭代器采用惰性求值的方式,它们可以在需要时才生成值,从而节省内存。
  • 支持无限序列:迭代器可以处理无限序列,因为它们是按需生成值的。
  • 解耦迭代逻辑:迭代器将迭代逻辑与容器类型分离,使得不同的容器类型可以共享相同的迭代逻辑。

iter()

在Python中,iter() 函数是一个内置函数,用于获取一个迭代器。迭代器是一个实现了迭代协议的对象,它允许你逐个访问容器(如列表、元组、字符串等)中的元素,而无需一次性在内存中加载所有元素。这使得迭代器在处理大型数据集时非常高效。

基本用法

iterator = iter(iterable)  
iterator = iter(callable, sentinel)

参数:

  • iterable:一个可以迭代的对象,如列表、元组、字符串、字典、集合等。
  • callable:一个无参数的可调用对象(如函数),每次调用时返回迭代器的下一个值,直到它返回 sentinel。
  • sentinel:一个标记值,用于指示迭代结束。当 callable 返回这个值时,迭代停止。
  • 返回值:返回一个迭代器对象。

案例

使用 iter() 获取迭代器

my_list = [1, 2, 3, 4, 5]  
iterator = iter(my_list)  
  
# 使用 next() 函数遍历迭代器  
while True:  
    try:  
        value = next(iterator)  
        print(value)  
    except StopIteration:  
        break

输出

1  
2  
3  
4  
5

使用 iter() 和 callable、sentinel

def my_generator():  
    count = 0  
    while True:  
        yield count  
        count += 1  
  
# 创建一个迭代器,当生成器返回特定值时停止迭代  
iterator = iter(my_generator(), 5)  
  
# 使用 next() 函数遍历迭代器  
while True:  
    try:  
        value = next(iterator)  
        print(value)  
    except StopIteration:  
        break

输出

0  
1  
2  
3  
4

在这个例子中,my_generator() 是一个生成器函数,它每次调用 next() 时返回一个值。我们使用 iter() 函数和 sentinel 参数来创建一个迭代器,当生成器返回 5 时停止迭代。

超出数据条数会报错

my_list = [1, 2, 3, 4, 5]
iterator = iter(my_list)
print(next(iterator)) # 输出:1
print(next(iterator)) # 输出:2
print(next(iterator)) # 输出:3
print(next(iterator)) # 输出:4
print(next(iterator)) # 输出:5
#再输出就没有值了,就会出现报错
print(next(iterator))
#报错信息如下:
#     print(next(iterator))
# StopIteration

注意事项

  • 迭代器只能向前移动,不能回退。
  • 一旦迭代器被耗尽(即所有元素都被访问过),它就不能再产生新的值。如果你尝试再次使用耗尽的迭代器,它将立即引发 StopIteration 异常。
  • 使用 iter() 和 next() 手动迭代容器是一种低级的迭代方式。在大多数情况下,你更可能使用循环(如 for 循环)来自动处理迭代。

自定义迭代器类

class MyRange:  
    """  
    一个自定义的迭代器类,用于生成从start到end(不包括end)的数字。  
    """  
      
    def __init__(self, start, end):  
        """  
        初始化方法。  
          
        :param start: 起始数字  
        :param end: 结束数字(不包括)  
        """  
        self.current = start  # 当前数字,从start开始  
        self.end = end  # 结束数字,迭代到这个数字之前停止  
      
    def __iter__(self):  
        """  
        使对象成为迭代器的方法(实现迭代协议的一部分)。  
          
        :return: 返回迭代器对象自身  
        """  
        return self  
      
    def __next__(self):  
        """  
        返回迭代器的下一个值。  
          
        :return: 下一个数字,如果到达end则引发StopIteration异常  
        """  
        if self.current < self.end:  
            num = self.current  # 存储当前数字  
            self.current += 1  # 移动到下一个数字  
            return num  # 返回存储的数字  
        else:  
            raise StopIteration  # 如果到达或超过end,则停止迭代  
  
# 示例运行代码  
if __name__ == "__main__":  
    # 创建一个MyRange对象,表示从0到5的数字  
    my_range = MyRange(0, 5)  
      
    # 使用for循环遍历迭代器  
    print("Using for loop:")  
    for number in my_range:  
        print(number)  
      
    # 手动使用next()函数遍历迭代器  
    print("\nUsing next() function:")  
    iterator = iter(my_range)  # 注意:这里会重新初始化迭代器,但my_range对象已经耗尽,所以下面会立即引发StopIteration  
    # 由于上面的for循环已经耗尽了迭代器,我们需要重新创建一个MyRange对象来演示next()的使用  
    iterator = iter(MyRange(0, 5))    
    while True:  
        try:  
            number = next(iterator)  
            print(number)  
        except StopIteration:  
            break

运行结果:

Using for loop:  
0  
1  
2  
3  
4  
  
Using next() function:  
0  
1  
2  
3  
4
  • 在上面的代码中,MyRange 类实现了两个特殊方法:iter() 和 next(),这使得它的实例可以作为迭代器使用。
  • iter() 方法返回迭代器对象自身,这是实现迭代协议的要求之一。
  • next() 方法返回迭代器的下一个值,并在没有更多值可供返回时引发 StopIteration 异常。
  • 在示例运行代码中,首先使用 for 循环遍历了 MyRange 对象。由于迭代器是惰性求值的,并且只能遍历一次,因此第二次尝试使用 next() 函数遍历时,我们重新创建了一个 MyRange 对象。
  • 在实际应用中,你可能希望设计一个更加健壮的迭代器类,比如能够处理反向迭代、步长等。这个示例仅展示了最基本的功能。

推荐阅读

Python基础

Python全网最全基础课程笔记(一)——基础入门
Python全网最全基础课程笔记(二)——变量
Python全网最全基础课程笔记(三)——所有运算符+运算符优先级
Python全网最全基础课程笔记(四)——基本数据类型
Python全网最全基础课程笔记(五)——选择结构+Python新特性Match
Python全网最全基础课程笔记(六)——循环结构
Python全网最全基础课程笔记(七)——列表,跟着思维导图和图文来学习,爆肝2w字,无数代码案例!
Python全网最全基础课程笔记(八)——字典,跟着思维导图和图文来学习,爆肝2w字,无数代码案例!
Python全网最全基础课程笔记(九)——集合,跟着思维导图和图文来学习,爆肝2w字,无数代码案例!
Python全网最全基础课程笔记(十)——元组,跟着思维导图和图文来学习,爆肝2w字,无数代码案例!
Python全网最全基础课程笔记(十一)——字符串所有操作,跟着思维导图和图文来学习,爆肝2w字,无数代码案例!
Python全网最全基础课程笔记(十二)——函数,跟着思维导图和图文来学习,爆肝2w字,无数代码案例!
Python全网最全基础课程笔记(十三)——作用域,跟着思维导图和图文来学习,爆肝2w字,无数代码案例!

Flink入门到就业

2024年最新Flink教程,从基础到就业,大家一起学习–基础篇
2024年最新Flink教程,从基础到就业,大家一起学习–入门篇
2024年最新Flink教程,从基础到就业,大家一起学习–Flink集群部署
2024年最新Flink教程,从基础到就业,大家一起学习–flink部署和集群部署(从本地测试到公司生产环境如何部署项目源码)
2024年最新Flink教程,从基础到就业,大家一起学习–Flink运行架构底层源码详解+实战
2024年最新Flink教程,从基础到就业,大家一起学习–Flink DataStream API-第一篇+源码讲解

在这里插入图片描述


http://www.kler.cn/news/339007.html

相关文章:

  • MySQL 篇-深入了解视图、SQL 优化(主键优化、order by 优化、group by 优化、update 优化等)
  • 1.一、MyBatis入门
  • JS进阶 3——深入面向对象、原型
  • 费曼学习法没有输出对象怎么办?
  • 算法专题三: 二分查找
  • 【STM32单片机_(HAL库)】4-2-1【定时器TIM】定时器输出PWM实现呼吸灯实验
  • vue3组件通信之defineEmits
  • (C语言贪吃蛇)15.贪吃蛇吃食物
  • QD1-P5 HTML常用标签:段落和换行
  • 麒麟系统串口配置篇
  • Qt教程(001):Qt概述与安装
  • 如何实现 C/C++ 与 Python 的通信?
  • 【算法笔记】二分算法原理的深度剖析
  • 数据分析认知
  • 17 链表——21. 合并两个有序链表 ★
  • 【小技巧】mysql 判断表字段是否存在 删除字段 sql脚本
  • python爬虫 - 进阶requests模块
  • 【机器学习-无监督学习】降维与主成分分析
  • 命名管道Linux
  • Stable Diffusion绘画 | 如何做到不同动作表情,人物角色保持一致性(下篇)