python高级7.多任务--协程-迭代器

2023-11-13

迭代器

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

  1. 可迭代对象(iterable object)

我们已经知道可以对list、tuple、str等类型的数据使用for…in…的循环语法从其中依次拿到数据进行使用,我们把这样的过程称为遍历,也叫迭代。

但是,是否所有的数据类型都可以放到for…in…的语句中,然后让for…in…每次从中取出一条数据供我们使用,即供我们迭代吗?

for i in 100:
… print(i)

Traceback (most recent call last):
File “”, line 1, in
TypeError: ‘int’ object is not iterable

#int整型不是iterable,即int整型不是可以迭代的

#我们自定义一个容器MyList用来存放数据,可以通过add方法向其中添加数据

class MyList(object):
… def init(self):
… self.container = []
… def add(self, item):
… self.container.append(item)

mylist = MyList()
mylist.add(1)
mylist.add(2)
mylist.add(3)
for num in mylist:
… print(num)

Traceback (most recent call last):
File “”, line 1, in
TypeError: ‘MyList’ object is not iterable

#MyList容器的对象也是不能迭代的

我们自定义了一个容器类型MyList,在将一个存放了多个数据的MyList对象放到for…in…的语句中,发现for…in…并不能从中依次取出一条数据返回给我们,也就说我们随便封装了一个可以存放多条数据的类型却并不能被迭代使用。

我们把可以通过for…in…这类语句迭代读取一条数据供我们使用的对象称之为可迭代对象(Iterable)**。

  1. 如何判断一个对象是否可以迭代
    可以使用 isinstance() 判断一个对象是否是 Iterable 对象:

In [50]: from collections import Iterable

In [51]: isinstance([], Iterable)
Out[51]: True

In [52]: isinstance({}, Iterable)
Out[52]: True

In [53]: isinstance(‘abc’, Iterable)
Out[53]: True

In [54]: isinstance(mylist, Iterable)
Out[54]: False

In [55]: isinstance(100, Iterable)
Out[55]: False

3.可迭代对象的本质

我们分析对可迭代对象进行迭代使用的过程,发现每迭代一次(即在for…in…中每循环一次)都会返回对象中的下一条数据,一直向后读取数据直到迭代了所有数据后结束。那么,在这个过程中就应该有一个“人”去记录每次访问到了第几条数据,以便每次迭代都可以返回下一条数据。我们把这个能帮助我们进行数据迭代的“人”称为迭代器(Iterator)。

可迭代对象的本质就是可以向我们提供一个这样的中间“人”即迭代器帮助我们对其进行迭代遍历使用。

可迭代对象通过__iter__方法向我们提供一个迭代器,我们在迭代一个可迭代对象的时候,实际上就是先获取该对象提供的一个迭代器,然后通过这个迭代器来依次获取对象中的每一个数据.

那么也就是说,一个具备了__iter__方法的对象,就是一个可迭代对象。

class MyList(object):
… def init(self):
… self.container = []
… def add(self, item):
… self.container.append(item)
… def iter(self):
… “”“返回一个迭代器”""
… # 我们暂时忽略如何构造一个迭代器对象
… pass

mylist = MyList()
from collections import Iterable
isinstance(mylist, Iterable)
True

#这回测试发现添加了__iter__方法的mylist对象已经是一个可迭代对象了

4.iter()函数与next()函数

list、tuple等都是可迭代对象,我们可以通过iter()函数获取这些可迭代对象的迭代器。然后我们可以对获取到的迭代器不断使用next()函数来获取下一条数据。iter()函数实际上就是调用了可迭代对象的__iter__方法。

li = [11, 22, 33, 44, 55]
li_iter = iter(li)
next(li_iter)
11

next(li_iter)
22

next(li_iter)
33

next(li_iter)
44

next(li_iter)
55

next(li_iter)
Traceback (most recent call last):
File “”, line 1, in
StopIteration

注意,当我们已经迭代完最后一个数据之后,再次调用next()函数会抛出StopIteration的异常,来告诉我们所有数据都已迭代完成,不用再执行next()函数了。

5.如何判断一个对象是否是迭代器

可以使用isinstance()判断一个对象是否是Iterator:

In [56]: from collections import Iterator

In [57]: isinstance([], Iterator)
Out[57]: False

In [58]: isinstance(iter([]), Iterator)
Out[58]: True

In [59]: isinstance(iter(“abc”), Iterator)
Out[59]: True

6.迭代器Iterator

通过上面的分析,我们已经知道,迭代器是用来帮助我们记录每次迭代访问到的位置,当我们对迭代器使用next()函数的时候,迭代器会向我们返回它所记录位置的下一个位置的数据。实际上,在使用next()函数的时候,调用的就是迭代器对象的__next__方法(Python3中是对象的__next__方法,Python2中是对象的next()方法)。所以,我们要想构造一个迭代器,就要实现它的__next__方法。但这还不够,python要求迭代器本身也是可迭代的,所以我们还要为迭代器实现__iter__方法,而__iter__方法要返回一个迭代器,迭代器自身正是一个迭代器,所以迭代器的__iter__方法返回自身即可。

一个实现了__iter__方法和__next__方法的对象,就是迭代器。

class MyList(object):
“”“自定义的一个可迭代对象”""
def init(self):
self.items = []

def add(self, val):
    self.items.append(val)

def __iter__(self):
    myiterator = MyIterator(self)
    return myiterator

class MyIterator(object):
“”“自定义的供上面可迭代对象使用的一个迭代器”""
def init(self, mylist):
self.mylist = mylist
# current用来记录当前访问到的位置
self.current = 0

def __next__(self):
    if self.current < len(self.mylist.items):
        item = self.mylist.items[self.current]
        self.current += 1
        return item
    else:
        raise StopIteration

def __iter__(self):
    return self

if name == ‘main’:
mylist = MyList()
mylist.add(1)
mylist.add(2)
mylist.add(3)
mylist.add(4)
mylist.add(5)
for num in mylist:
print(num)

7.for…in…循环的本质

for item in Iterable 循环的本质就是先通过iter()函数获取可迭代对象Iterable的迭代器,然后对获取到的迭代器不断调用next()方法来获取下一个值并将其赋值给item,当遇到StopIteration的异常后循环结束。

8.迭代器的应用场景

我们发现迭代器最核心的功能就是可以通过next()函数的调用来返回下一个数据值。如果每次返回的数据值不是在一个已有的数据集合中读取的,而是通过程序按照一定的规律计算生成的,那么也就意味着可以不用再依赖一个已有的数据集合,也就是说不用再将所有要迭代的数据都一次性缓存下来供后续依次读取,这样可以节省大量的存储(内存)空间。

举个例子,比如,数学中有个著名的斐波拉契数列(Fibonacci),数列中第一个数为0,第二个数为1,其后的每一个数都可由前两个数相加得到:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …

现在我们想要通过for…in…循环来遍历迭代斐波那契数列中的前n个数。那么这个斐波那契数列我们就可以用迭代器来实现,每次迭代都通过数学计算来生成下一个数。
class FibIterator(object):
“”“斐波那契数列迭代器”""
def init(self, n):
“”"
:param n: int, 指明生成数列的前n个数
“”"
self.n = n
# current用来保存当前生成到数列中的第几个数了
self.current = 0
# num1用来保存前前一个数,初始值为数列中的第一个数0
self.num1 = 0
# num2用来保存前一个数,初始值为数列中的第二个数1
self.num2 = 1
def next(self):
“”“被next()函数调用来获取下一个数”""
if self.current < self.n:
num = self.num1
self.num1, self.num2 = self.num2, self.num1+self.num2
self.current += 1
return num
else:
raise StopIteration
def iter(self):
“”“迭代器的__iter__返回自身即可”""
return self
if name == ‘main’:
fib = FibIterator(10)
for num in fib:
print(num, end=" ")

  1. 并不是只有for循环能接收可迭代对象

除了for循环能接收可迭代对象,list、tuple等也能接收。
li = list(FibIterator(15))
print(li)
tp = tuple(FibIterator(6))
print(tp)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python高级7.多任务--协程-迭代器 的相关文章

  • Lighttpd 和 cgi python

    我正在尝试通过 lighttpd 执行一些 python 脚本 但是当我尝试运行它时 我只得到一个要求我下载的空白文件 lighttpd conf server modules mod access mod alias mod access
  • 是否有解决方法可以通过 CoinGecko API 安全检查?

    我在工作中运行我的代码 一切都很顺利 但在不同的网络 家庭 WiFi 上 我不断收到403访问时出错CoinGecko V3 API https www coingecko com api documentations v3 可以观察到 在
  • 中断 Select 以添加另一个要在 Python 中监视的套接字

    我正在 Windows XP 应用程序中使用 TCP 实现点对点 IPC 我正在使用select and socketPython 2 6 6 中的模块 我有三个 TCP 线程 一个读取线程通常会阻塞select 一个通常等待事件的写入线程
  • 元组有什么用?

    我现在正在学习 Python 课程 我们刚刚介绍了元组作为数据类型之一 我阅读了它的维基百科页面 但是 我无法弄清楚这种数据类型在实践中会有什么用处 我可以提供一些需要一组不可变数字的示例吗 也许是在 Python 中 这与列表有何不同 每
  • 在 django ORM 中查询时如何将 char 转换为整数?

    最近开始使用 Django ORM 我想执行这个查询 select student id from students where student id like 97318 order by CAST student id as UNSIG
  • 跟踪 pypi 依赖项 - 谁在使用我的包

    无论如何 是否可以通过 pip 或 PyPi 来识别哪些项目 在 Pypi 上发布 可能正在使用我的包 也在 PyPi 上发布 我想确定每个包的用户群以及可能尝试积极与他们互动 预先感谢您的任何答案 即使我想做的事情是不可能的 这实际上是不
  • Python zmq SUB 套接字未接收 MQL5 Zmq PUB 套接字

    我正在尝试在 MQL5 中设置一个 PUB 套接字 并在 Python 中设置一个 SUB 套接字来接收消息 我在 MQL5 中有这个 include
  • 为什么 PyYAML 花费这么多时间来解析 YAML 文件?

    我正在解析一个大约 6500 行的 YAML 文件 格式如下 foo1 bar1 blah name john age 123 metadata whatever1 whatever whatever2 whatever stuff thi
  • “隐藏”内置类对象、函数、代码等的名称和性质[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我很好奇模块中存在的类builtins无法直接访问的 例如 type lambda 0 name function of module
  • 在 Sphinx 文档中*仅*显示文档字符串?

    Sphinx有一个功能叫做automethod从方法的文档字符串中提取文档并将其嵌入到文档中 但它不仅嵌入了文档字符串 还嵌入了方法签名 名称 参数 我如何嵌入only文档字符串 不包括方法签名 ref http www sphinx do
  • 如何通过 TLS 1.2 运行 django runserver

    我正在本地 Mac OS X 机器上测试 Stripe 订单 我正在实现这段代码 stripe api key settings STRIPE SECRET order stripe Order create currency usd em
  • 如何通过索引列表从 dask 数据框中选择数据?

    我想根据索引列表从 dask 数据框中选择行 我怎样才能做到这一点 Example 假设我有以下 dask 数据框 dict A 1 2 3 4 5 6 7 B 2 3 4 5 6 7 8 index x1 a2 x3 c4 x5 y6 x
  • 不同编程语言中的浮点数学

    我知道浮点数学充其量可能是丑陋的 但我想知道是否有人可以解释以下怪癖 在大多数编程语言中 我测试了 0 4 到 0 2 的加法会产生轻微的错误 而 0 4 0 1 0 1 则不会产生错误 两者计算不平等的原因是什么 在各自的编程语言中可以采
  • 如何断言 Unittest 上的可迭代对象不为空?

    向服务提交查询后 我会收到一本字典或一个列表 我想确保它不为空 我使用Python 2 7 我很惊讶没有任何assertEmpty方法为unittest TestCase类实例 现有的替代方案看起来并不正确 self assertTrue
  • 如何在 pygtk 中创建新信号

    我创建了一个 python 对象 但我想在它上面发送信号 我让它继承自 gobject GObject 但似乎没有任何方法可以在我的对象上创建新信号 您还可以在类定义中定义信号 class MyGObjectClass gobject GO
  • 如何解决 PDFBox 没有 unicode 映射错误?

    我有一个现有的 PDF 文件 我想使用 python 脚本将其转换为 Excel 文件 目前正在使用PDFBox 但是存在多个类似以下错误 org apache pdfbox pdmodel font PDType0Font toUnico
  • 模拟pytest中的异常终止

    我的多线程应用程序遇到了一个错误 主线程的任何异常终止 例如 未捕获的异常或某些信号 都会导致其他线程之一死锁 并阻止进程干净退出 我解决了这个问题 但我想添加一个测试来防止回归 但是 我不知道如何在 pytest 中模拟异常终止 如果我只
  • 如何应用一个函数 n 次? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 假设我有一个函数 它接受一个参数并返回相同类型的结果 def increment x return x 1 如何制作高阶函数repeat可以
  • Pandas 每周计算重复值

    我有一个Dataframe包含按周分组的日期和 ID df date id 2022 02 07 1 3 5 4 2022 02 14 2 1 3 2022 02 21 9 10 1 2022 05 16 我想计算每周有多少 id 与上周重
  • 使用随机放置的 NaN 创建示例 numpy 数组

    出于测试目的 我想创建一个M by Nnumpy 数组与c随机放置的 NaN import numpy as np M 10 N 5 c 15 A np random randn M N A mask np nan 我在创建时遇到问题mas

随机推荐

  • GB/T28181-2016传输要求和Android平台设备接入技术实现

    相关协议规范 GB T28181 2016公共安全视频监控联网系统 信息传输 交换 控制技术要求相关的传输要求如下 5 1 网络传输协议要求 联网系统网络层应支持IP协议 传输层应支持 TCP和 UDP协议 5 2 媒体传输协议要求 视音频
  • 用一张图说一说 ChatGPT 内部技术工作流程

    前沿 这几天ChatGPT可谓是热火朝天 很多同事和朋友都来找到勇哥 说能不能说一说相关话题 但是之前几天勇哥都在默默的干一件大事情 今天终于成型 有结果了 所有就抽了点时间来和大家一起聊聊ChatGPT背后的技术 让大家对一自然语言处理背
  • docker+fastdfs+springboot一键式搭建分布式文件服务器

    首先说一下从零开始自己去搭一个fastdfs有多不顺 搭起来步骤繁琐 很麻烦 后来看到有人把做好的docker镜像传出来了 那搭建起来就很容易了 有服务器的可以自己在服务器上玩玩 没有的可以新建一个centos7 5虚拟机玩玩 遇到虚拟机不
  • (待解决)0x00007FF7CECD5E7A 处有未经处理的异常(在 ImageWarp.exe 中): 0xC0000005: 写入位置 0x0000000000006080 时发生访问冲突。

    0x00007FF7CECD5E7A 处有未经处理的异常 在 ImageWarp exe 中 0xC0000005 写入位置 0x0000000000006080 时发生访问冲突 不知道如何是好
  • Transformer的稳健性更好吗?

    点击下方卡片 关注 CVer 公众号 AI CV重磅干货 第一时间送达 本文作者 Greene 来源 知乎 已获作者授权 https zhuanlan zhihu com p 361105702 最近 Transformer 在计算机视觉遍
  • Spring七大组件

    一 Spring七大组件 1 核心容器 Spring core Spring core相当于一个创建并管理bean的容器 创建 底层使用反射技术创建bean的实例 管理 容器中的每个bean spring容器默认按照单例模式管理 设计 使用
  • Unity-网络开发(一)

    网络基本概念 网络 网络的作用 在没有网络之前 每个人的设备 电脑等 都是彼此孤立的 网络的出现让设备之间可以相互通信 网络是由若干设备和连接这些设备的链路构成 各种设备 间接或者直接通过介质相连 设备之间想要进行信息传递时 将想要传递的数
  • idea中Git设置(http/ssh)方式

    最近用IDEA上的git功能出现了可以commit但无法push和pull的问题 测试发现原因是Could not read from remote repository 在Stack Overflow上发现了解决方法 在Settings
  • python构建发布_Python代码的构建与发布(Windows环境)

    1 首先将写好注释的代码保存在一个文件夹nester下 2 在这个文件夹下创建一个文件setup py 用来编辑模块的元数据 from distutils core import setup 从发布工具导入setup函数 setup nam
  • 什么叫持久化? 为什么持久化?(转)

    1 应用程序层次结构演变 这里本来应该有张描述应用程序结构演变的图 可是CSDN在这里上传不了 所以没有传上来 纵观几十年的计算机应用软件的演变过程 应用程序逐渐由单层体系结构发展为多层体系结构 最初应用软件只是在大型机上的单层应用程序 大
  • quill实现上传文件

    1 首先工具栏配置加上upload 如图 这时会发现上传图片没有显示出来 需要自定义一个上传的图标 在阿里云矢量图标库下载一个就可以了 2 图标样式修改 deep ql upload background url assets img up
  • JavaScript undeclared 与 undefined 的区别

    undefined 声明了变量 但是没有赋值 undeclared 没有声明变量就直接使用 如上图 num 就是undefined arr 则是 undeclared
  • 蓝桥杯Python初级测试题之省赛题1

    蓝桥杯Python初级测试题之省赛题1 1 统计成绩及格率和优秀率 题目描述 小L给学生们组织了一场考试 卷面总分为 100 分 每个学生的得分都是一个 0 到 100 的整数 如果得分至少是 60 分 则称为及格 如果得分至少为 85 分
  • C++实现矩阵乘法

    本贴分享用C 实现矩阵乘法计算的功能 具体内容请看代码和注释 这里单独说一明一部分代码块 1 采用vector lt vector
  • 【操作系统】王道考研 笔记总结目录(完结)

    写在前面 视频链接 是为了期末考和以后就业的笔记 第一章 操作系统 王道考研 p1 操作系统的概念 功能和目标 操作系统 王道考研 p2 操作系统的四个特征 操作系统 王道考研 p3 操作系统的发展与分类 操作系统 王道考研 p4 操作系统
  • Ruby简介 完全面对象 脚本 从人的角度编程(强大反射)

    Ruby 一种为简单快捷面向对象编程而创的脚本语言 在20世纪90年代由日本人松本行弘开发 遵守GPL协议和Ruby License 1 它的灵感与特性来自于Perl Smalltalk Eiffel Ada以及Lisp语言 由Ruby语言
  • 启动IDEA发现我的项目模块/代码没了

    依次点击 文件 项目结构 模块 导入模块
  • 【C++】基本数据类型

    C 基本数据类型是程序中最基本的数据类型 它们是构建复杂数据类型的基础 C 中的基本数据类型包括整型 浮点型 字符型和布尔型等 目录 基本数据类型 整型 浮点型 字符型 转义字符 字符串 布尔类型 sizeof 基本数据类型 整型 作用 用
  • 算法学习笔记——动态规划:不连续取值的前提下求最大总和

    LeetCode 198 打家劫舍 一排房屋 某房屋内的金额数为nums i 相邻房屋内的钱不能被同时取出 求最多能取出多少钱 nums 1 1 3 4 返回5 选择取出1 4 5 dp i 代表对于0 i号房屋 能取走的最大金额 依次考虑
  • python高级7.多任务--协程-迭代器

    迭代器 迭代是访问集合元素的一种方式 迭代器是一个可以记住遍历的位置的对象 迭代器对象从集合的第一个元素开始访问 直到所有的元素被访问完结束 迭代器只能往前不会后退 可迭代对象 iterable object 我们已经知道可以对list t