【Python迭代器探秘】:揭秘迭代器与生成器的魔法,掌握高效循环的艺术

文章目录

  • 一、迭代器的基本概念
    • 1.1 迭代器优点
    • 1.2 迭代器的编写方法
    • 1.3 python内置迭代器函数
    • 1.4 小结
    • 1.5 迭代器对象与迭代对象
      • 1.5.1 区别
        • 1. 迭代对象
        • 2. 迭代器对象
        • 3. 小结
      • 1.5.2 方法区分
  • 二、生成器基本概念
    • 1. 生成器函数
    • 2. 生成器表达式

在这里插入图片描述

一、迭代器的基本概念

迭代器是Python语言中的一个重要特性,用于遍历可迭代对象(如列表、元组、字典等)中的元素。Python中的很多内置对象都支持迭代器模式,可以通过iter()函数获取一个迭代器对象,并使用next()方法逐一访问其中的元素。

my_list = [1, 2, 3, 4, 5]
my_iterator = iter(my_list)

while True:
    try:
        value = next(my_iterator)
        print(value)
    except StopIteration:
        break

# 首先使用iter()函数获取列表my_list的迭代器对象,并进入一个无限循环中,
# 逐一使用next()方法获取其元素并进行打印。当迭代器抛出StopIteration异常时,循环终止(结束)。


迭代器是一个定义了__iter__()__next__()方法的对象。在Python中,很多内置对象都是可以被迭代的,例如列表、元组、字典、集合等。

当我们对一个可迭代对象使用iter()函数时,会得到一个迭代器对象。然后,就可以使用next()方法逐一访问该对象中的元素,直到迭代器抛出StopIteration异常为止。

通常情况下,我们不需要直接调用 iter() 方法来获取迭代器对象,而是通过使用 for 循环对可迭代对象进行遍历。当使用 for 循环语句时,如果要对一个对象进行迭代,程序会自动调用该对象的 iter() 方法,返回一个迭代器对象,然后使用迭代器对象进行迭代操作。

1.1 迭代器优点

  • 更加高效:与传统的for循环相比,在大型数据集上使用迭代器可以减少内存消耗,节省系统资源;

  • 更加灵活:迭代器允许我们以任意方式遍历数据集,包括正向、反向、跳跃等操作;

  • 更加通用:几乎所有Python内置容器类型都是可迭代的,因此迭代器可以应用于各种不同的数据类型。

1.2 迭代器的编写方法

迭代器的编写方法非常简单,只需要定义一个支持__iter__()__next__()方法的类即可。
__iter__ ()方法返回迭代器对象本身,而__next__()方法则返回下一个元素,在到达末尾时抛出StopIteration异常。
需要注意的是,对于无法提前预知迭代对象长度的情况,要在实现__next__()方法时添加相应的终止条件。

class MyIterator:
    def __init__(self, string):
        self.string = string
        self.index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index == len(self.string):
            raise StopIteration
        result = self.string[self.index]
        self.index += 1
        return result

my_iterator = MyIterator("Hello, world!")

for char in my_iterator:
    print(char)

在这里插入图片描述

自定义了一个迭代器类MyIterator,并在其中实现了__iter__()__next__()方法。对于字符串类型的输入,__next__()方法会逐一返回其中的字符,直到遇到结尾为止。

1.3 python内置迭代器函数

map(function, iterable):将一个函数应用于可迭代对象的每个元素,并返回一个新的迭代器对象,其中包含了应用后的结果;

filter(function, iterable):将一个函数应用于可迭代对象的每个元素,并返回一个新的迭代器对象,其中仅包含满足条件的元素;

zip(*iterables):将多个可迭代对象中相应位置的元素组合在一起,并返回一个新的元组迭代器对象;

reversed(iterable):翻转一个可迭代对象中的元素顺序,并返回一个新的迭代器对象。

my_list = [1, 2, 3, 4, 5]
new_list = list(map(lambda x: x ** 2, my_list))
print(new_list)

even_list = list(filter(lambda x: x % 2 == 0, my_list))
print(even_list)

my_tuple = ("apple", "banana", "cherry")
my_dict = {"name": "John", "age": 36, "country": "Norway"}
for item in zip(my_list, my_tuple, my_dict):
    print(item)

for char in reversed("Hello, world!"):
    print(char)

在这里插入图片描述

1.4 小结

迭代器是Python语言中的一个非常重要的特性,可以方便地遍历各种数据类型。

Python内置了很多支持迭代器模式的对象,同时也提供了一些常用的内置迭代器函数,包括map()、filter()、zip()和reversed()等。

在使用迭代器时,需要注意终止条件和异常处理等细节问题,以确保代码能够正确地遍历数据集。

1.5 迭代器对象与迭代对象

1.5.1 区别

1. 迭代对象

一个对象如果可以通过 for 循环进行遍历,则称其为迭代对象。

序列类型,如 list、tuple 和 string;
非序列类型,如 dict、set、file 等。

# 通过 __iter__() 方法可以获取一个迭代器对象,该方法在迭代对象中已经被实现。

# 换句话说,迭代对象 只存在 __iter__()

# 列表中调用 __iter__() 方法后,就可以得到一个迭代器对象

lst = [1, 2, 3]
it = lst.__iter__()  # 获取列表的迭代器对象
print(dir(lst)) 
print(dir(it)) 

为了让一个对象可以被迭代,只需要确保其实现了 iter() 方法,即可满足迭代协议。当我们使用 for 循环遍历该对象时,Python 会自动调用其 iter() 方法,从而得到一个迭代器对象并进行迭代操作。

2. 迭代器对象

迭代器对象是一种可以逐个访问元素的对象,并且只能向前遍历。迭代器对象可以使用 next()函数获取下一个值,如果没有更多的元素,则会引发 StopIteration 异常。

迭代器对象必须包含以下两个方法:

  • __iter__() 方法返回迭代器对象本身;
  • __next__() 方法返回下一个值,如果没有下一个值,则引发 StopIteration 异常。

我们可以使用普通函数或生成器函数来创建迭代器对象。例如,在 Python 中,我们可以使用 iter() 函数将可迭代对象转换为迭代器对象:

# 使用普通函数或生成器函数来创建迭代器对象

lst = [1, 2, 3]
it = iter(lst)  # 将列表转换为迭代器对象

需要注意的是,一旦我们使用 next() 函数获取了迭代器对象中的某个元素,该元素就从迭代器对象中消失了。因此,迭代器对象只能用于一次遍历。

3. 小结
  • 迭代器对象可以逐个访问元素,且只能向前遍历;

  • 迭代对象可以通过__iter__()方法获取一个迭代器对象;

  • 迭代器对象必须包含 __iter__() __next__() 方法;

  • 迭代器对象只能用于一次遍历,而迭代对象不受此限制。

1.5.2 方法区分

Python的 collections.abc 模块中的 Iterable 和 Iterator 类来判断一个对象是否为迭代对象和迭代器对象

导入 collections.abc 模块中的 Iterable 和 Iterator 类。然后,定义一个列表 lst 和一个生成器 gen,并分别使用 isinstance() 函数和 Iterable 或 Iterator 类对其进行判断。
在输出结果中,可以看到,列表 lst 是一个迭代对象,但不是一个迭代器对象;而生成器 gen 同时属于迭代对象和迭代器对象。

注意:在判断一个对象是否为迭代器对象时,必须先保证它是一个迭代对象,否则会出现错误。

from collections.abc import Iterable, Iterator

lst = [1, 2, 3]  # 列表属于迭代对象,但不是迭代器对象
gen = (i for i in range(5))  # 生成器属于迭代器对象,也属于迭代对象

print(isinstance(lst, Iterable))  # True
print(isinstance(gen, Iterable))  # True

print(isinstance(lst, Iterator))  # False
print(isinstance(gen, Iterator))  # True

在这里插入图片描述

二、生成器基本概念

生成器(generator)是 Python 中一种特殊的迭代器,它是一种函数或表达式,可以在运行时逐个产生值,并且只会在需要时进行计算。

与列表、元组等序列类型不同,生成器并不会一次性把所有元素计算出来并保存在内存中,而是按需生成每个值,从而节省了大量的计算资源和存储空间。

生成器创建:
生成器函数:通过使用 yield 语句将一个函数转换为生成器;

生成器表达式:类似于列表推导式,使用 (expr for var in iterable) 的形式来创建生成器对象。

1. 生成器函数

生成器函数是一种特殊的 Python 函数,它可以暂停执行并返回中间结果。当调用生成器函数时,它不会立即执行函数体中的所有代码,而是返回一个生成器(generator)对象。然后,我们可以使用 next() 或 send() 方法逐步迭代该生成器,并在需要时生成新值。

生成器函数可以使用 yield 语句来暂停函数执行并返回中间值。在函数执行期间,可以多次使用 yield 语句返回多个中间结果。每次调用生成器函数时,它都从上次停止的位置继续执行,并在遇到新的 yield 语句时返回相应的中间结果。

# 使用生成器函数创建斐波那契数列生成器
def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

# 创建一个 Fibonacci 数列生成器
fib = fibonacci()

# 生成前10个 Fibonacci 数字
for i in range(10):
    print(next(fib))

在这里插入图片描述

定义了一个 fibonacci 函数,它使用 yield 语句暂停执行并返回每个斐波那契数列中的数字。然后将其赋值给 fib 变量,并使用 next() 函数依次获取它返回的每个中间值,并在循环中输出前10个 Fibonacci 数字。

send() 方法将值发送到生成器。send() 方法类似于 next() 方法,但它可以在生成器中传递一个值,并且该值会成为生成器中 yield 的表达式的结果。

def my_generator():
    while True:
        val = yield     # 中间值接收
        if val is not None:
            print(f"Received value: {val}")
        else:
            print("No value received")

gen = my_generator()

next(gen)       # 启动生成器

gen.send(10)    # 向生成器发送值 10
gen.send("Hello")   # 向生成器发送字符串 "Hello"
gen.send(None)  # 向生成器发送空值

在这里插入图片描述

定义了一个 my_generator() 函数,它使用 while True 循环不断返回 yield 所产生的值,并在 yield 语句中使用变量 val 来接收 send() 方法所发送的值。通过调用 next() 方法启动生成器后,我们可以使用 send() 方法向其发送数据,从而在每次调用时产生新值。同时,我们还可以通过判断接收到的值是否为空来控制程序的行为。

使用 send() 方法将值发送到生成器,并让生成器在需要时返回相应的中间结果。与 next() 方法不同,send() 方法可以在生成器中接收一个值,并且该值会成为生成器中 yield 的表达式的结果。这种机制可以帮助我们更好地控制生成器的行为,从而实现更高效、更功能强大的程序。

2. 生成器表达式

生成器表达式是一种生成器构造形式,它类似于列表推导式,但是在语法上略有不同。
它们使用圆括号而不是方括号来括起来,并使用 (expr for var in iterable) 的形式来生成新元素,从而节省了大量的计算资源和存储空间。

# 使用生成器表达式创建一个数字生成器
gen = (i for i in range(5))

# 迭代生成器以产生数字
for num in gen:
    print(num)

在这里插入图片描述

使用生成器表达式创建了一个数字生成器,它将生成从0到4的五个数字。然后使用 for 循环遍历该生成器并输出每个数字。
生成器是 Python 中一种强大的工具,它们可以逐个生成值,并节省计算和存储空间。通过使用 yield 语句定义生成器函数或使用生成器表达式,我们可以轻松地构建和使用生成器,减少计算和存储成本,提高程序效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/780800.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一.2.(2)基本共射放大电路组成、工作原理;

1.基本共射放大电路组成 共什么取决于输入输出,共剩下的那一极 2.工作原理 输入信号ui通过电容C1加到三极管的基 极,引起基极电流iB的变化,iB的变化又使集电极电流ic发生变 化,且ic的变化量是iB变化量的β倍。由于有集电极电压&…

【数据结构】05.双向链表

一、双向链表的结构 注意:这里的“带头”跟前面我们说的“头节点”是两个概念,带头链表里的头节点,实际为“哨兵位”,哨兵位节点不存储任何有效元素,只是站在这里“放哨的”。 “哨兵位”存在的意义:遍历循…

Django QuerySet对象,filter()方法

filter()方法 用于实现数据过滤功能&#xff0c;相当于sql语句中的where子句。 filter(字段名__exact10) 或 filter(字段名10)类似sql 中的 10 filter(字段名__gt10) 类似SQL中的 >10 filter(price__lt29.99) 类似sql中的 <29.99 filter(字段名__gte10, 字段名__lte20…

LightGlue: Local Feature Matching at Light Speed【文献阅读】

论文&#xff1a;LightGlue: Local Feature Matching at Light Speed 代码&#xff1a;https://github.com/cvg/LightGlue 作者&#xff1a;1 ETH Zurich__2 Microsoft Mixed Reality & AI Lab Abstract 提出的LightGlue是一个深度神经网络用于学习图像间的局部特征匹配。…

基于AOP的数据字典实现:实现前端下拉框的可配置更新

作者&#xff1a;后端小肥肠 创作不易&#xff0c;未经允许严禁转载。 目录 1. 前言 2. 数据字典 2.1. 数据字典简介 2.2. 数据字典如何管理各模块的下拉框 3. 数据字典核心内容解读 3.1. 表结构 3.2. 核心代码 3.2.1. 根据实体类名称获取下属数据字典 3.2.2. 数据字…

python库(6):Pygments库

1 Pygments介绍 在软件开发和文档编写中&#xff0c;代码的可读性是至关重要的一环。无论是在博客文章、技术文档还是教程中&#xff0c;通过代码高亮可以使程序代码更加清晰和易于理解。而在Python世界中&#xff0c;Pygments库就是这样一个强大的工具&#xff0c;它能够将各…

【YOLOv9教程】如何使用YOLOv9进行图像与视频检测

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

【论文阅读】AsyncDiff: Parallelizing Diffusion Models by Asynchronous Denoising

论文&#xff1a;2406.06911 (arxiv.org) 代码&#xff1a;czg1225/AsyncDiff: Official implementation of "AsyncDiff: Parallelizing Diffusion Models by Asynchronous Denoising" (github.com) 简介 异步去噪并行化扩散模型。提出了一种新的扩散模型分布式加…

python脚本“文档”撰写——“诱骗”ai撰写“火火的动态”python“自动”脚本文档

“火火的动态”python“自动”脚本文档&#xff0c;又从ai学习搭子那儿“套”来&#xff0c;可谓良心质量&#x1f44d;&#x1f44d;。 (笔记模板由python脚本于2024年07月07日 15:15:33创建&#xff0c;本篇笔记适合喜欢钻研python和页面源码的coder翻阅) 【学习的细节是欢悦…

001uboot体验

1.uboot的作用&#xff1a; 上电->uboot启动->关闭看门狗、初始化时钟、sdram、uart等外设->把内核文件从flash读取到SDRAM->引导内核启动->挂载根文件系统->启动根文件系统的应用程序 2.uboot编译 uboot是一个通用的裸机程序&#xff0c;为了适应各种芯片&…

盘点8款国内顶尖局域网监控软件(2024年国产局域网监控软件排名)

局域网监控软件对于企业网络管理至关重要&#xff0c;它们可以帮助IT部门维护网络安全&#xff0c;优化网络性能&#xff0c;同时监控和控制内部员工的网络使用行为。以下是八款备受推崇的局域网监控软件&#xff0c;每一款都有其独特的优势和适用场景。 1.安企神软件 试用版领…

【数据结构】(C语言):二叉搜索树(不使用递归)

二叉搜索树&#xff1a; 非线性的&#xff0c;树是层级结构。基本单位是节点&#xff0c;每个节点最多2个子节点。有序。每个节点&#xff0c;其左子节点都比它小&#xff0c;其右子节点都比它大。每个子树都是一个二叉搜索树。每个节点及其所有子节点形成子树。可以是空树。 …

Report Design Analysis报告之logic level详解

目录 一、前言 二、Logic Level distribution 2.1 logic level配置 2.2 Logic Level Distribution报告 2.3 Logic Level 报告详情查看 2.4 Route Distributions 报告详情查看 2.5 示例代码 一、前言 ​在工程设计中&#xff0c;如果需要了解路径的逻辑级数&#xff0c;可…

赚钱小思路,送给没有背景的辛辛苦苦努力的我们!

我是一个没有背景的普通人&#xff0c;主要靠勤奋和一股钻劲&#xff0c;这十几年来我的日常作息铁打不变&#xff0c;除了睡觉&#xff0c;不是在搞钱&#xff0c;就是在琢磨怎么搞钱。 ​ 可以说打拼了十几年&#xff0c;各种小生意都做过&#xff0c;以前一直是很乐观的&…

绘唐3最新版本哪里下载

绘唐3最新版本哪里下载 绘唐最新版本下载地址 推文视频创作设计是一种通过视频和文字的形式来进行推广的方式&#xff0c;可以通过一些专业的工具来进行制作。 以下是一些常用的小说推文视频创作设计工具&#xff1a; 视频剪辑软件&#xff1a;如Adobe Premiere Pro、Fina…

人工智能系列-Pandas基础

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” Pandas简介 Pandas是Python语言的拓展程序库&#xff0c;用于数据分析。 Pandas是一个开放源码&#xff0c;BSD许可的库&#xff0c;提供高性能&#xff0c;易于使用的数据结…

SSM养老院管理系统-计算机毕业设计源码02221

摘要 本篇论文旨在设计和实现一个基于SSM的养老院管理系统&#xff0c;旨在提供高效、便捷的养老院管理服务。该系统将包括老人档案信息管理、护工人员管理、房间信息管理、费用管理等功能模块&#xff0c;以满足养老院管理者和居民的不同需求。 通过引入SSM框架&#x…

ChatGPT对话:Scratch编程中一个单词,如balloon,每个字母行为一致,如何优化编程

【编者按】balloon 7个字母具有相同的行为&#xff0c;根据ChatGPT提供的方法&#xff0c;优化了代码&#xff0c;方便代码维护与复用。初学者可以使用7个字母精灵&#xff0c;复制代码到不同精灵&#xff0c;也能完成这个功能&#xff0c;但不是优化方法&#xff0c;也没有提高…

微信小程序毕业设计-医院挂号预约系统项目开发实战(附源码+论文)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;微信小程序毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计…

高考志愿填报,选专业是看兴趣还是看就业?

对于结束高考的学生来说&#xff0c;选择专业的确是一个非常让人头疼的事情。因为很多人都不知道&#xff0c;选专业的时候究竟是应该看一下个人兴趣&#xff0c;还是看未来的就业方向&#xff0c;这也是让不少人都相当纠结的问题。这里分析一下关于专业选择的问题&#xff0c;…