Python 中的迭代器(iter、next)与生成器(yield)解析

Python 中的迭代器(Iterator)是一个可以记住遍历位置的对象,用于迭代列表、元组、字典、集合和字符串等可迭代(Iterable)对象,迭代器从集合的第一个元素开始访问,直到所有的元素被访问完结束,并且只能往前不会后退。使用 collections.abc 库中的 Iterable 和 Iterator 可以判断对象是否可迭代和是否为迭代器。

>>> from collections.abc import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance(100, Iterable)
False
>>> from collections.abc import Iterator
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True

正如上面代码所示,列表、字典和字符串都是可迭代的,而数字就不是可迭代的。但列表、字典和字符串都不是迭代器,因为可迭代的对象(如列表、元组、字典、集合和字符串),得先使用 iter() 方法把它们初始化为迭代器对象之后,才能使用 next() 方法对其进行迭代。所以 iter([])iter('abc') 都是迭代器。

有了迭代器之后,就可以用 next() 方法对其进行迭代,如果迭代器的内容已经全部迭代完了,就会返回一个 StopIteration 的错误:

>>> list=[1, 2, 3, 4]
>>> it = iter(list)    # 创建迭代器对象
>>> print (next(it))   # 输出迭代器的下一个元素
1
>>> print (next(it))
2
>>> print (next(it))
3
>>> print (next(it))
4
>>> print (next(it))
Traceback (most recent call last):File "<stdin>", line 1, in <module>
StopIteration

不断地调用 next() 方法显然太麻烦了,最简洁的方法是使用 for 循环

>>> for i in [1, 2, 3, 4]:
...     print(i)
... 
1
2
3
4

注意 for 循环接收的只是可迭代对象而不是迭代器,所以实际上 for 循环帮我们同时完成了 iter()next() 方法,并且在遇到 StopIteration 就会自动退出循环。以下代码和上面是等价的:

it = iter([1, 2, 3, 4, 5])  # 创建迭代器对象
# 循环:
while True:try:i = next(it)  # 输出迭代器的下一个元素print(i)except StopIteration:  # 遇到StopIteration就退出循环break

说完迭代器,就轮到生成器了。所谓生成器(generator) 就是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器

生成器(函数)有两种写法,第一种是类似于列表生成式(推导式) 的写法,只不过把列表的中括号换成小括号而已:

>>> f = (x * x for x in range(10))
>>> f
<generator object <genexpr> at 0x1022ef630>

f 就是一个迭代器,其函数为求平方,所以能使用 next() 方法进行迭代:

>>> next(f)
0
>>> next(f)
1
>>> next(f)
4
>>> next(f)
9
>>> next(f)
16
>>> next(f)
25
>>> next(f)
36
>>> next(f)
49
>>> next(f)
64
>>> next(f)
81
>>> next(g)
Traceback (most recent call last):File "<stdin>", line 1, in <module>
StopIteration

同样地,用 for 循环既然能处理可迭代对象,当然也可以处理迭代器,如下

>>> f = (x * x for x in range(10))
>>> for i in f:
...     print(i)
... 
0
1
4
9
16
25
36
49
64
81

第二种生成器的写法,就是在创建函数时使用 yield 关键字,假设我们想输出指定长度的斐波拉契数列,有如下函数:

def fib(max):n, a, b = 0, 0, 1while n < max:print(b)a, b = b, a + bn = n + 1return 'done'

调用函数如下:

>>> fib(6)
1
1
2
3
5
8
'done'

只需要把函数中的 print 改为 yield,该函数就变成了生成器函数:

def fib(max):n, a, b = 0, 0, 1while n < max:yield ba, b = b, a + bn = n + 1return 'done'

调用生成器函数就会得到一个生成器,实际上也就是迭代器:

>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>

所以用 for 循环进行迭代可以得到如下结果:

>>> for i in f:
...     print(i)
... 
1
1
2
3
5
8

生成器函数普通函数的执行流程不一样。普通函数是顺序执行,遇到 return 语句或者最后一行函数语句就返回。而变成生成器的函数,在每次调用 next() 的时候执行,遇到 yield 语句返回,再次执行时从上次返回的 yield 语句处继续执行。

最后作个总结:

  • 迭代器一定是可迭代的,但集合数据类型如列表、字典、字符串等是可迭代的但不是迭代器,可以通过 iter() 函数获得一个迭代器对象;
  • 凡是可作用于 for 循环的对象都是可迭代的
  • 凡是可作用于 next() 函数的对象都是迭代器,它们表示一个惰性计算的序列;
  • Python 的 for 循环如果接收到还不是迭代器可迭代的对象,就会调用 iter() 将其变成迭代器,然后不断调用 next() 函数实现迭代过程;
  • 生成器就是可以让我们通过编写函数,自定义得到的迭代器

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯-卡片-填空题

一:题目 二:思路 1是最快消耗完的计算1的个数即可 三&#xff1a;上码 #include <iostream> using namespace std; int main() {int ans 0;int count 0;for(int i 1; i < 20000; i) {string str to_string(i);// cout << str << endl;for(int j …

跟我一起学.NetCore之Swagger让前后端不再烦恼及界面自定义

前言随着前后端分离开发模式的流行&#xff0c;接口对接、联调成为常事&#xff0c;前端同事会经常问&#xff1a;我需要调哪个接口&#xff1f;这个接口数据格式是啥&#xff1f;条件都传啥&#xff1f; 对于一些紧急接口可能会采取沟通对接&#xff0c;然后补文档&#xff0c…

由浅入深,带你搞懂 Pytorch 中的张量 tensor 是什么

目录1、tensor 是什么&#xff1f;2、tensor 的三个属性2.1 Rank 秩2.2 Axis&#xff08;复数 为 Axes&#xff09; 轴2.3 Shape 形状3、Pytorch 中 torch.Tensor 的三个属性3.1 torch.dtype3.2 torch.device3.3 torch.layout4、创建张量的两种方法4.1 从现有数据创建张量4.2 凭…

蓝桥杯-排序-填空题

一:题目 二:上码 #include <iostream> using namespace std; int main() {// 请在此输入您的代码/**/**冒泡排序中:我们考虑到最坏的情况,那就是全都是逆序 那么就需要交换 N(N-1)/2; 那么100次 最起码需要 15个字符&#xff0c;而15个字符完全逆序的话 需要交换 105次…

打造钉钉事件分发平台之钉钉审批等事件处理

前言上讲和上上讲我们说到了钉钉的审批和钉钉通讯录的一个简单示例&#xff0c;这次我们讲下如何快速打造一个自己的钉钉事件分发平台。让你能够通过监听用户在钉钉上的操作&#xff0c;然后进行对应的业务处理&#xff0c;比如钉钉流程审批完后业务处理、通讯录员工增加后对应…

Pytorch 中 Dataset 和 DataLoader,以及 torchvision 的 datasets 完全理解

目录1、torch.utils.data.Dataset()2、torch.utils.data.Sampler()3、torch.utils.data.DataLoader()4、torchvision.datasets.ImageFolder()5、例子 torchvision.datasets.FashionMNIST()1、torch.utils.data.Dataset() 首先最基础的&#xff0c;是 torch.utils.data.Dataset…

蓝桥杯-成绩分析-编程题

一:题目 二&#xff1a;上码 #include<bits/stdc.h> using namespace std;int main() {int n;cin >> n;vector<int> v(n,0);for (int i 0; i < n; i) {cin >> v[i];}sort(v.begin(),v.end());double sum accumulate(v.begin(),v.end(),0);double…

BeetleX框架详解-小结

到这里BeetleX组件代码讲解完成了&#xff0c;由于组件只封装了TCP基础通讯的功能&#xff0c;因此在内容上并不会有太多&#xff1b;通以上内容相信对BeetleX的设计有一定的了解&#xff0c;在使用上也更加容易。要点Socket对象应用SocketAsyncEventArgs对象应用线程池的应用与…

深度学习入门笔记 —— 循环神经网络 RNN

首先&#xff0c;明确 RNN 的主要任务是用于文本分类&#xff0c;而解决文本分类任务最经典的模型是词袋模型&#xff08;Bag-of-Words Model&#xff09;&#xff0c;如图所示&#xff0c;输入是三个句子&#xff0c;词袋模型首先要定义一个词汇表 vocabulary&#xff0c;里面…

深圳店匠笔试题-4.01

一:题目类型 10个选择10个填空2道编程题 二&#xff1a;编程题 1&#xff1a;34 在排序数组中查找元素的第一个和最后一个位置 class Solution { public:/**思路:1.分为两种情况 那就是该元素是存在于排序数组当中,该元素不存在该排序数组当中。2.如果元素是存在于排序数组当…

进击吧! Blazor !第二期 回顾

Blazor 是一个 Web UI 框架&#xff0c;可通过 WebAssembly 在任意浏览器中运行 .Net 。Blazor 旨在简化快速的单页面 .Net 浏览器应用的构建过程&#xff0c;它虽然使用了诸如 CSS 和 HTML 之类的 Web 技术&#xff0c;但它使用 C&#xff03;语言和 Razor 语法代替 JavaScrip…

蓝桥杯-长草-代码(BFS)

一:题目 题目描述 小明有一块空地&#xff0c;他将这块空地划分为 nn 行 mm 列的小块&#xff0c;每行和每列的长度都为 1。 小明选了其中的一些小块空地&#xff0c;种上了草&#xff0c;其他小块仍然保持是空地。 这些草长得很快&#xff0c;每个月&#xff0c;草都会向外…

Pytorch 中 LSTM 和 LSTMCell 的区别

LSTM 的官方文档在这里 在例子中&#xff1a; LSTM 函数的参数为输入特征向量的长度 input_size 10、隐藏层向量的长度 hidden_size 20、隐藏层的数量 num_layers 2&#xff1b; 输入 input 的维度是时间/序列长度&#xff08;句子有多少个单词&#xff09; time_steps 5、…

程序员修神之路--缓存架构不够好,系统容易瘫痪

“灵魂拷问缓存能大幅度提高系统性能&#xff0c;也能大幅度提高系统瘫痪几率怎么样防止缓存系统被穿透&#xff1f;缓存的雪崩是不是可以完全避免&#xff1f;前几篇文章我们介绍了缓存的优势以及数据一致性的问题&#xff0c;在一个面临高并发系统中&#xff0c;缓存几乎成了…

Leetcode 数据结构与算法题解大全——目录(推荐收藏,持续更新)

为了方便查找写过的题解&#xff0c;我按照不同的类型将题解进行了归类&#xff0c;这里做个目录置顶。 由于牛客网笔试时可能用的是ACM模式&#xff0c;所以可以看看这篇博客&#xff0c;做做入门练习就理解了。刷题顺序的话&#xff0c;可以按我的这篇博客刷。 数学&#x…

Magicodes.IE之花式导出

总体设计Magicodes.IE是一个导入导出通用库&#xff0c;支持Dto导入导出以及动态导出&#xff0c;支持Excel、Word、Pdf、Csv和Html。在本篇教程&#xff0c;笔者将讲述如何使用Magicodes.IE进行花式导出。在本篇教程&#xff0c;笔者主要讲述如何使用IE进行花式导出并满足客户…

京东笔试4.2-19:00随笔

30道选择考察到了数据结构&#xff0c;计网&#xff0c;linux,数据库&#xff0c;java基础&#xff0c;就记得这些了 两道编程题 一道二叉树 一道 动态规划 一道也没AC出来 第一道需要会做的前提是 需要创建二叉树 并给其赋值 然后再谈算法 因为一直刷leetcode&#xff0c;转换…

我又踩坑了!如何为HttpClient请求设置Content-Type标头?

最近在重构认证代码&#xff0c;认证过程相当常规&#xff1a;POST /open-api/v1/user-info?client_id&timstamp&rd12345&sign***&methodhmac content-type: application/json payload: { "token":"AA2917B0-C23D-40AB-A43A-4C4B61CC7C74&qu…

利用数组创建二叉树并赋值

1:二叉树的创建与赋值 (1):前言知识 这里的创建是利用层序序列进行创建,主要就是根节点的坐标为i 的话 那么左节点的坐标为 2i1,右节点的坐标为2i2;开辟一个结构体 struct Node {int val;Node * left;Node * right;Node () : val(-1),left(NULL),right(NULL) {};Node(int x)…

2020 中国开源年会(COSCon'20)再启程:开源向善(Open Source for Good)

中国开源年会COSCon2020正式启动&#xff01;*本图由开源社设计组叶凯设计时间&#xff1a;2020年10月24-25日线上直播地址&#xff1a;bilibili & Youtube讲师互动平台&#xff1a;Zoom时间弹指飞逝&#xff0c;转眼即过去了一年。不知道各位在这多舛的半年间又和开源这二…