Python:可迭代对象与迭代器

相关阅读

Pythonicon-default.png?t=N7T8https://blog.csdn.net/weixin_45791458/category_12403403.html?spm=1001.2014.3001.5482


        根据Python官方文档,可迭代对象(iterable)是“一种能够逐个返回其成员项的对象”。具体来说,这种对象要么定义了一个返回迭代器(iterator)的魔术方法__iter__(),要么定义了魔术方法__getitem__(),并使用从0开始的整数索引。

        Python中的一些内置类型就是可迭代对象,比如列表(list)、元组(tuple)、range对象、字符串(str)、字典(dict)、集合(set),下面的例子检测了这些类型是否拥有__iter__()方法或__getitem__()方法:

List  = [1, 2, 3]
Tuple = (1, 2, 3)
Range = range(1, 4)
Str   = 'hello, world!'
Dict  = {'name': 'Alice', 'age': 13, 'gender': 'Female'}
Set   = {1, 2, 3}

# 检测是否包含 __getitem__ 方法
print("List has __getitem__:", hasattr(List, '__getitem__'))
print("Tuple has __getitem__:", hasattr(Tuple, '__getitem__'))
print("Range has __getitem__:", hasattr(Range, '__getitem__'))
print("Str has __getitem__:", hasattr(Str, '__getitem__'))
print("Dict has __getitem__:", hasattr(Dict, '__getitem__'))
print("Set has __getitem__:", hasattr(Set, '__getitem__'))

# 检测是否包含 __iter__ 方法
print("List has __iter__:", hasattr(List, '__iter__'))
print("Tuple has __iter__:", hasattr(Tuple, '__iter__'))
print("Range has __iter__:", hasattr(Range, '__iter__'))
print("Str has __iter__:", hasattr(Str, '__iter__'))
print("Dict has __iter__:", hasattr(Dict, '__iter__'))
print("Set has __iter__:", hasattr(Set, '__iter__'))

        结果显示,它们大多都实现了这两个魔术方法,除了集合没有实现__getitem__()方法,如下所示。

输出:
List has __getitem__: True
Tuple has __getitem__: True
Range has __getitem__: True
Str has __getitem__: True
Dict has __getitem__: True
Set has __getitem__: False
List has __iter__: True
Tuple has __iter__: True
Range has __iter__: True
Str has __iter__: True
Dict has __iter__: True
Set has __iter__: True

        collections.abc.Iterable是一个基类,可以用它检测一个对象是否拥有__iter__()方法,如下所示。

from collections.abc import Iterable
# 检测是否含有__iter__()
print("List is Iterable:", isinstance(List, Iterable))
print("Tuple is Iterable:", isinstance(Tuple, Iterable))
print("Range is Iterable:", isinstance(Range, Iterable))
print("Str is Iterable:", isinstance(Str, Iterable))
print("Dict is Iterable:", isinstance(Dict, Iterable))
print("Set is Iterable:", isinstance(Set, Iterable))
# 输出:
List is Iterable: True
Tuple is Iterable: True
Range is Iterable: True
Str is Iterable: True
Dict is Iterable: True
Set is Iterable: True

        但这不是一个可靠的检测方式,因为如果一个可迭代对象只拥有__getitem__()方法,则这种方式就会失效。一个可靠的方式是使用Python内置函数iter()。

        可迭代对象可以使用内置函数iter()转化为迭代器(iterator),iter()函数首先会尝试调用可迭代对象的__iter__()方法返回一个迭代器(是否是迭代器是根据返回对象是否拥有__next__方法检测的,如返回的不是迭代器则会产生TypeError异常: iter() returned non-iterator of type ***),如果不存在__iter__()方法,则会寻找是否有索引从0开始的__getitem__()方法并尝试创建一个迭代器,如果仍然不存在,则会引发TypeError异常。

        下面展示了一些内置类型使用iter()函数创建的迭代器,直接使用__iter__()方法也可返回迭代器,但它不检测返回的是否是迭代器,因此最好使用iter()函数。

# 检测迭代器的类型
ListIter = iter(List)    # 直接使用List.__iter__()方法也可返回迭代器
print(type(ListIter))  
TupleIter = iter(Tuple)  # 直接使用Tuple.__iter__()方法也可返回迭代器
print(type(TupleIter))
RangeIter = iter(Range)  # 直接使用Range.__iter__()方法也可返回迭代器
print(type(RangeIter))
StrIter = iter(Str)      # 直接使用Str.__iter__()方法也可返回迭代器
print(type(StrIter))
DictIter = iter(Dict)    # 直接使用Dict.__iter__()方法也可返回迭代器
print(type(DictIter))
SetIter = iter(Set)      # 直接使用Set.__iter__()方法也可返回迭代器
print(type(SetIter))

# 输出:
<class 'list_iterator'>
<class 'tuple_iterator'>
<class 'range_iterator'>
<class 'str_iterator'>
<class 'dict_keyiterator'>
<class 'set_iterator'>

        迭代器拥有__iter__()方法(用于返回自己,因此迭代器本身也是可迭代对象),和__next__()方法(用于迭代)。

        for循环其实就是迭代的过程,首先会调用iter()函数为可迭代对象创建一个未命名的迭代器,再循环的过程中调用__next__()方法进行迭代,直到迭代器耗尽,触发StopIteration异常并停止循环,并销毁未命名的迭代器。

        使用内置函数next()也可以进行迭代,它们之间的差别不大,如下所示。

# 使用列表迭代器
print(next(ListIter))
print(ListIter.__next__()) 
print(next(ListIter))
print(ListIter.__next__()) 

# 输出:
1
2
3
StopIteration Traceback (most recent call last)

        注意从 Python 3.7 开始,字典的遍历顺序一定和输入顺序一样。所以字典迭代器的迭代顺序是确定的,对字典使用iter()函数,默认返回的是针对键的迭代器,可以通过使用values()方法或items()方法明确指定想要遍历的元素,并返回相应的迭代器。

# 使用字典迭代器
print(next(DictIter))
print(next(DictIter))
print(next(DictIter))

ValueIter = iter(Dict.values())
print(next(ValueIter))
print(next(ValueIter))
print(next(ValueIter))

输出:
name
age
gender
Alice
13
Female

        集合迭代器无法保证遍历顺序,因此不应该对此有任何期待。

        下面的例子定义了一个,只含有__getitem__()方法的可迭代对象,并直接使用循环迭代,还创建了一个迭代器并用next()函数进行迭代。

class MyIterable:
    def __init__(self, data):
        self.data = data

    def __getitem__(self, index):
        return self.data[index]

# 示例用法
my_iterable = MyIterable([1, 2, 3, 4, 5])

for item in my_iterable:
    print(item)

my_iterator = iter(my_iterable)
print(next(my_iterator))
print(next(my_iterator))
print(next(my_iterator))

输出:
1
2
3
4
5
1
2
3

        迭代器对象只能按照顺序前行,无法后退,这意味着对于一个迭代器对象,只能遍历一轮,如果想要多轮迭代,可以重新创建迭代器。

        写这篇文章的起因,是接触了神经网络框架Pytorch中的torchvision.datasets包,里面定义了很多数据集,它们是拥有__getitem__()方法的可迭代对象,因此可以使用索引访问,而dataloader是拥有__iter__()方法的可迭代对象,所以不可以使用索引访问。

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

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

相关文章

如何实现Windows RDP 远程桌面异地跨网连接

Windows RDP远程桌面的应用非常广泛。远程桌面协议(RDP)是一个多通道(multi-channel)的协议&#xff0c;让使用者(所在计算机称为用户端或本地计算机)连上提供微软终端机服务的计算机(称为服务端或远程计算机)。大部分的Windows版本都有用户端所需软件&#xff0c;有些其他操作…

太阳能路灯光伏板的朝向设计问题

题目&#xff1a;太阳能路灯光伏板的朝向设计问题 难度对标几乎每一年的国赛A题。 QQ群&#xff1a;592697532 公众号&#xff1a;川川菜鸟 文章目录 背景问题问题一问题二问题三 题目解读相关公式&#xff08;必备&#xff09;太阳辐射的计算光伏板接收的辐射光学效率大 气透…

数据结构(顺序栈

目录 1. 讲解&#xff1a;2. C代码实现&#xff1a;小结&#xff1a; 1. 讲解&#xff1a; 用顺序的物理结构&#xff08;数组&#xff09;存储栈这个数据结构&#xff0c;实现栈的创建、销毁、增删查、判空。 top指针的指向位置有两种实现方法&#xff1a;一个是指向栈顶元素…

云服务器部署Springboot项目

前端项目打包 修改ip地址 在控制台输入npm run build:prod 会产生dist文件 将dist文件中的内容移动至/usr/local/nginx/html目录下 后端项目打包 修改ip地址 执行clean操作 执行install操作 将生成的target文件中的jar包移动至/usr/local/src目录下 启动 注意⚠️&#xff…

前沿论文 | LLM推理性能优化最佳实践

原文&#xff1a;安全验证 - 知乎​ 来源 题目&#xff1a;LLM Inference Performance Engineering: Best Practices 地址&#xff1a;https://www.databricks.com/blog/llm-inference-performance-engineering-best-practices 在这篇博文中&#xff0c;MosaicML工程团队分析了…

AI讲师人工智能讲师大模型培训讲师叶梓:突破大型语言模型推理效率的创新方法

大型语言模型&#xff08;LLM&#xff09;在自然语言处理&#xff08;NLP&#xff09;任务中展现出了前所未有的能力&#xff0c;但它们对计算资源的巨大需求限制了其在资源受限环境中的应用。SparQ Attention算法提出了一种创新的方法&#xff0c;通过减少注意力机制中的内存带…

HBuilder真机调试检测不到荣耀Magic UI系列(包括手机和电脑)解决办法

HBuilder真机调试检测不到荣耀Magic UI系列&#xff08;包括手机和电脑&#xff09;解决办法解决方法&#xff1a; 1.在开发人员选项中开启USB调试 如何进入开发者选项&#xff1f; 设置->关于->版本号&#xff0c;点击版本号直至出现您已处于开发者模式 2.选择USB配置…

Github 2024-04-19Java开源项目日报 Top9

根据Github Trendings的统计,今日(2024-04-19统计)共有9个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Java项目9HTML项目1Android开发者实用工具集 创建周期:2820 天开发语言:Java协议类型:Apache License 2.0Star数量:32909 个Fork数量:10631…

北大字节联合发布视觉自动回归建模(VAR):通过下一代预测生成可扩展的图像

北大和字节发布一个新的图像生成框架VAR。首次使GPT风格的AR模型在图像生成上超越了Diffusion transformer。 同时展现出了与大语言模型观察到的类似Scaling laws的规律。在ImageNet 256x256基准上,VAR将FID从18.65大幅提升到1.80,IS从80.4提升到356.4,推理速度提高了20倍。 相…

设计模式——策略模式20

策略模式是一种行为设计模式&#xff0c; 它能让你定义多种算法或行为方式&#xff0c; 并将具体实现放入独立的类中&#xff0c; 以使算法的对象能够相互替换。使用场景例如活动中多种打折策略。 策略抽象 /*** author ggbond* date 2024年04月18日 08:02*/ public interfa…

Linux 系统下的进程间通信 IPC 入门 「中」

以下内容为本人的学习笔记&#xff0c;如需要转载&#xff0c;请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/39XQUQtGC3Ow-0s0JKWnog 信号量 信号量一般用于配合共享内存的数据传输&#xff0c;共享内存被多个进程之间共享访问&#xff0c;各个进程对共享…

Arcade 用户界面textarea

# 导入所需库 import arcade import arcade.gui# 创建窗口类 class MyWindow(arcade.Window):# 初始化方法def __init__(self):super().__init__(800, 600, "GUI Widgets Example", resizableTrue)# 创建UI管理器&#xff0c;用于处理UI元素self.manager arcade.gui…

2024Mathorcup数学应用挑战赛C题|图神经网络的预测模型+ARIMA时间序列预测模型+人员排班混合整数规划模型|完整代码和论文全解全析

2024Mathorcup数学应用挑战赛C题|图神经网络的预测模型ARIMA时间序列预测模型人员排班混合整数规划模型|完整代码和论文全解全析 我们已经完成了2024Mathorcup数学建模挑战赛C题的40页完整论文和代码&#xff0c;相关内容可见文末&#xff0c;部分图片如下&#xff1a; 问题分…

N元语言模型

第1关&#xff1a;预测句子概率 任务描述 本关任务&#xff1a;利用二元语言模型计算句子的概率 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.条件概率计算方式。 2.二元语言模型相关知识。 条件概率计算公式 条件概率是指事件A在事件B发生的条件下发…

Golang | Leetcode Golang题解之第36题有效的数独

题目&#xff1a; 题解&#xff1a; func isValidSudoku(board [][]byte) bool {var rows, columns [9][9]intvar subboxes [3][3][9]intfor i, row : range board {for j, c : range row {if c . {continue}index : c - 1rows[i][index]columns[j][index]subboxes[i/3][j/3]…

【每日一题】2007. 从双倍数组中还原原数组-2024.4.18

题目&#xff1a; 2007. 从双倍数组中还原原数组 一个整数数组 original 可以转变成一个 双倍 数组 changed &#xff0c;转变方式为将 original 中每个元素 值乘以 2 加入数组中&#xff0c;然后将所有元素 随机打乱 。 给你一个数组 changed &#xff0c;如果 change 是 双…

如何获得合适的助听器?

要获得一个合适的助听器&#xff0c;您可以按照以下步骤进行&#xff1a; 1. 咨询专业医生或听力专家&#xff1a;首先&#xff0c;建议您咨询专业的耳鼻喉科医生或听力专家。他们可以通过听力测试来评估您的听力损失程度和类型&#xff0c;并为您提供个性化的建议。 2. 选择信…

DevOps是什么?

DevOps是一系列实践、工具和文化理念的组合&#xff0c;旨在自动化并整合软件开发和信息技术运维团队之间的流程。以下是DevOps的几个关键点&#xff1a; 沟通与协作&#xff1a;DevOps强调开发和运维团队之间的沟通与合作&#xff0c;通过改善这两个部门间的协作关系&#xff…

Labview2024安装包(亲测可用)

目录 一、软件简介 二、软件下载 一、软件简介 LabVIEW是一种由美国国家仪器&#xff08;NI&#xff09;公司开发的程序开发环境&#xff0c;它显著区别于其他计算机语言&#xff0c;如C和BASIC。传统的计算机语言是基于文本的语言来产生代码&#xff0c;而LabVIEW则采用图形化…

JavaEE:File类查询一个文件的路径(举例+源码 )

一、File类概述 Java 中通过 java.io.File 类来对一个文件&#xff08;包括目录&#xff09;进行抽象的描述。File 类中的方法可以对文件路径以及文件名等信息进行查询&#xff0c;也可以对文件进行各项增删改操作&#xff0c;本文主要介绍 File 类的查询方法。 二、代码示例 …