Python高频面试题——迭代器和可迭代对象

news2024/10/6 4:01:31

 

无论是面试测试还是运维涉及到python编码岗位时,迭代器和可迭代对象都是绕不开的一个问题,本文对这两个概念进行重点讲解,本文从什么是迭代讲起,然后介绍迭代器和可迭代对象二者的区别,最后通过for 循环和自定义迭代器来加深读者对这两个概念的理解,只要认真阅读完文章,相信一定会帮助到大家,文章有点长,建议首收藏!

迭代

关于迭代,维基百科是这样子定义的:迭代是重复反馈过程的活动,其目的通常是为了接近并到达所需的目标或结果。每一次对过程的重复被称为一次“迭代”,而每一次迭代得到的结果会被用来作为下一次迭代的初始值。

在程序中,迭代是一种遍历集合元素的方式,我们最常用的迭代应用如下:

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

输出:

1

2

3

可迭代对象(iterable)

只要实现 __ iter __ 方法或者实现 __ getitem __方法而且其参数从0开始索引,那么该对象就是可迭代对象(iterable)。

Python 中的大多数内置数据结构(容器)都是可迭代对象,比如list、dict、tuple、set、string。创建一个可迭代对象的实例如下:

class IterableDemo(object):
     def __init__(self, components):
          self.components = list(components)
     def __iter__(self):
          return iter(self.components)
V1 = IterableDemo([1, 2, 3])
for i in V1:
    print(i)

输出

1

2

3

可以看到实例IterableDemo进行了迭代,该对象之所以能迭代,是因为实现了__ iter __ ()方法。当使用for循环时候,解释器会检查对象是否有__ iter __ ()方法,有的话就是调用它来获取一个迭代器。所以没有 __ iter __ ()方法但实现了__ getitem __ (),解释器会创建一个迭代器,尝试从0开始按顺序遍历元素。如果尝试失败,Python便会抛出TypeError错误。

看下面这个list的例子,l=[1,2,3]。这里 l是一个可迭代对象。

我们可以通过方法__iter__()和函数iter把list(可迭代对象)转变成list迭代器对象,代码如下

print(type(l))
print(type(l.__iter__()))
print(type(iter(l)))

输出

<class 'list'>

<class 'list_iterator'>

<class 'list_iterator'>

我们可以看到,list变成了list_iterator,证明list是可迭代对象!

a=123456

print(type(iter(a)))

输出

TypeError: 'int' object is not iterable

可见int 类型是不可迭代对象,也就是说调用iter(对象)函数,如果该对象不可迭代,就会抛出TypeError的错误。

迭代器(iterator)

Python 中的迭代器是一个可以迭代的对象,一个每次仅仅返回一个元素的对象。从技术上讲,Python 迭代器对象必须实现两个魔法方法:__iter__() 和 __next__()方法,统称为迭代器协议(iterator protocol)。

容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用 in , not in 关键字判断元素是否包含在容器中。通常这类数据结构把所有的元素存储在内存中(也有一些特列并不是所有的元素都放在内存)在Python中,常见的容器对象有:list、dequeue、set、dict、Counter、tuple、str等等。尽管绝大多数容器都提供了某种方式来获取其中的每一个元素,但这并不是容器本身提供的能力,而是 可迭代对象 赋予了容器这种能力,当然并不是所有的容器都是可迭代的(Bloom filter容器不可以迭代)。

我们执行以下代码,创建x 和y两个独立的迭代器。

l=[1,2,3]
x=iter(l)
y=iter(l)
print("y第一次调用:"+str(next(y)))
print("x第一次调用:"+str(next(x)))
print("y第二次调用:"+str(next(y)))
print("x第二次调用:"+str(next(x)))

输出

y第一次调用:1

x第一次调用:1

y第二次调用:2

x第二次调用:2

证明了

1. x、y是两个独立的迭代器,彼此不影响

2. 迭代器内部持有一个状态,该状态用于记录当前迭代所在的位置,调用next,每次都是按顺序获取对应的元素

那么究竟什么是迭代器呢?

迭代器是一个可以记住遍历位置的对象,其内部有一个状态用于记录迭代所在的位置,以便下次迭代时候能取出正确的元素。迭代器就像一个懒人一样,当你需要数据时候才会返回给你,否则就在等待下一次的调用。

迭代器技术主要应用在哪些地方呢?主要包括:

• for 循环

• 构建和扩展集合类型

• 逐行遍历文本文件

• 列表推导、字典推导和集合推导

• 元组拆包

• 调用函数时,使用*拆包

迭代器和可迭代对象总结

共性:他们都可以通过循环的形式进行迭代;

迭代器是可迭代对象, 但是可迭代对象不一定是迭代器,例如list是可迭代对象,但不是迭代器;

可以通过iter(可迭代对象)的方法来生成迭代器;

可迭代对象需要实现 __ iter __ 方法或者实现 __ getitem __方法而且其参数从0开始索引。注意可迭代对象不一定实现__ next__方法;

迭代器需要同时实现__ iter __ 方法和__next__ 方法,当使用next()函数时会调用__next__方法。

举一个经典的例子把

l=[1,2,3]
print(next(l))

输出error:

print(next(l))

TypeError: 'list' object is not an iterator

可见,list不是一个迭代器,因为他没有实现__next__方法

接下来执行代码,print(next(iter(l)))

输出

1

可见通过iter(l) 生成了迭代器,因此next操作可以顺利进行

for i in (iterable)的内部实现

在大多数情况下,我们不会一次次调用next方法去取值,而是通过 for i in (iterable)的方式,如下图:

循环背后的原理又是什么呢?

调用iter(容器对象,即可迭代对象,即上图中的x=[1,2,3])函数生成迭代器(如果调用成功)

通过迭代器的__next__()方法访问容器元素

如果没有元素了,将抛出StopIteration exception

循环捕获StopIteration exception后就会终止循环

自定义迭代器

如果想自定义迭代器,需要实现__iter_和__next__两个方法

from collections.abc import Iterable
class MyIterator:
     last = 0
     def __iter__(self):
          return self
     def __next__(self):
         self.last += 1
         if self.last > 5:
             raise StopIteration
         return self.last
my= MyIterator()
print(isinstance(my,Iterable))
for i in my:
print(i)

输出:

True

1

2

3

4

5

从输出结果可以看出my 是iterable对象,并完成了遍历工作!

大家可以自定义一个类,里面不实现__iter_和__next__两个方法,例如

class Demo:
    pass
demo= Demo()
print(type(iter(demo)))

输出:

TypeError: 'Demo' object is not iterable

原创不易,如果文章帮到了你,劳烦点赞转发!

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

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

相关文章

150万奖金:首届6G智能无线通信系统大赛正式上线

通信与人工智能技术的深度融合已成为无线通信系统发展的最重要方向之一&#xff0c;面向6G&#xff0c;通信与AI融合的角度和深度将进一步扩展&#xff0c;迎接“无限”可能。在6G研究的关键发展阶段&#xff0c;由IMT-2030(6G)推进组主办&#xff0c;中国信息通信研究院、华为…

【折腾服务器 3】群晖学习版中安装 Active Backup for Business 及相关配置 =)

Catch UP 书接上回&#xff0c;在 ESXi 中安装了群晖系统&#xff0c;这个系统主要是用来给 Windows 物理机做备份的&#xff0c;因此在本片主要讲解如何配置 Active Backup for Business 软件。 Chapter 1 设置存储空间 上一篇博客中&#xff0c;安装群晖时分配了一个 32GB…

rancher2.6.2 单机及高可用部署

rancher2.6.2 单机及高可用部署 文章目录rancher2.6.2 单机及高可用部署前言单机部署高可用部署k8s集成前言 1、服务器准备 单机部署&#xff1a; 机器名IP地址部署内容cpu核心数内存(G)硬盘(G)rancher-master192.168.0.18rancher2450 高可用部署&#xff1a; 机器名IP地址…

Linux环境下通过命令行连接WIFI

一. 前言 在调试ARTIK时由于Ubuntu系统不是图形化界面&#xff0c;需要下载相关安装包时发现未联网&#xff0c;因此对Linux下采用命令行连接wifi的具体操作步骤进行总结&#xff0c;对自己在操作过程中遇到的相关问题解决方法进行介绍&#xff0c;同时对于LINUX下无线网络调试…

JUC(一):线程池

个人博客地址&#xff1a; http://xiaohe-blog.top/index.php/archives/14/ 文章目录1. 为什么要使用线程池2. Executor3. ThreadPoolExecutor3.1 七个参数3.2 任务队列3.3 拒绝策略4. 创建线程池5. Executors5.1 CachedThreadPool5.2 FixedThreadPool5.3 SingleThreadExecutor…

Vue3 异步组件 suspense

vue在解析我们的组件时&#xff0c; 是通过打包成一个 js 文件&#xff0c;当我们的一个组件 引入过多子组件是&#xff0c;页面的首屏加载时间 由最后一个组件决定 优化的一种方式就是采用异步组件 &#xff0c;先给慢的组件一个提示语或者 骨架屏 &#xff0c;内容回来在显示…

大话测试数据(一)

导读&#xff1a;测试数据的准备至关重要&#xff0c;无论是手工测试还是自动化测试都要以良好的测试数据准备为基础。本文为霍格沃兹测试学院特邀嘉宾&#xff0c;某互联网巨头企业资深测试技术专家刘晓光&#xff08;skytraveler&#xff09;老师对测试数据管理实践的思考总结…

【K3s】第3篇 解决K3s状态一直是ContainerCreating

目录 1、遇到问题 2、问题解决 2.1 查看docker服务 2.2 增加docker中国镜像源 必看项 2.3 解决docker pull失败 3、结果展示 1、遇到问题 安装部署完k3s时遇到如下问题&#xff1a; sudo kubectl get pods -A pod 容器状态一直为&#xff1a;ContainerCreating 查看容…

现有项目集成seata的记录

背景&#xff1a;现有项目为springcloudnacos 的。但是没有分布式事务处理机制&#xff0c;偶发数据问题&#xff0c;现需要引入seata进行全局事务管理。简单记录一下改造和学习过程&#xff0c;过一段时间自己100%会忘的一干二净&#xff0c;并没有对其进行很深的研究。 前期…

IMX6ULL学习笔记(16)——GPIO输入接口使用【官方SDK方式】

一、GPIO简介 i.MX6ULL 芯片的 GPIO 被分成 5 组,并且每组 GPIO 的数量不尽相同&#xff0c;例如 GPIO1 拥有 32 个引脚&#xff0c; GPIO2 拥有 22 个引脚&#xff0c; 其他 GPIO 分组的数量以及每个 GPIO 的功能请参考 《i.MX 6UltraLite Applications Processor Reference M…

aosp 12/13/lineageos19.1 framework学习编译刷入小米手机,努比亚

hi&#xff0c;学员朋友&#xff0c;大家好&#xff01; 前期一直有同学在问我这边&#xff0c;学习framework需要什么额外设备么&#xff1f;这里其实我一直前期也是给学员说的&#xff0c;如果你是个新手&#xff0c;刚刚开始可以不用&#xff0c;完全可以跟着课程一起学习&a…

贪官产生的本质是什么——谈谈人性与制度的博弈未来

知乎上有人问&#xff1a;贪官产生的本质原因是什么&#xff1f;一直不太能理解贪官是怎么产生的&#xff0c;希望能请各位从人性、社会、特权、阶级、系统工程等角度帮忙分析一下。贪官产生的本质原因是什么&#xff1f;- 青润的回答 - 知乎 https://www.zhihu.com/question/3…

python 动态规划的应用;斐波那契数列,最优解,最优子序列

一、动态规划概念 动态规划&#xff08;Dynamic Programming&#xff0c;DP&#xff09;是运筹学的一个分支&#xff0c;是求解决策过程最优化的过程。20世纪50年代初&#xff0c;美国数学家贝尔曼&#xff08;R.Bellman&#xff09;等人在研究多阶段决策过程的优化问题时&…

IT30--IT与业务业务与ITIT价值(3年之约已满)

从大学开始。。。 读大学前压根就没有见过计算机这个东西&#xff08;不得不感慨信息技术发展之快&#xff09;。可能因为高考数学考的还不错的原因&#xff0c;选择了计算机这个专业&#xff0c;后来研究生读的也是计算机的相关专业。当时班里的女生少&#xff0c;但没想到一…

java中多线程的基础知识

Process与Thread&#xff1a; 程序是指一段静态的代码,是指令和数据的有序集合,其本身没有任何运行的含义,它能够完成某些功能,它是应用软件执行的蓝本&#xff0c;它是一个静态的概念。 进程是关于某个数据集合的一次运行活动,它是操作系统动态执行的基本单元,也是程序的一次…

C++中二叉树的递归遍历方法2-2

在《C中二叉树的递归非遍历方法3-3》中提到&#xff0c;二叉树的层序遍历的输出顺序是从根节点开始&#xff0c;一层一层横向遍历各个节点。如图1所示的二叉树&#xff0c;层序遍历的输出的输出顺序为“1->2->3->4->5->6”。 图1 二叉树结构 1 递归实现层序遍历…

计算机视觉 基于CUDA编程的入门与实践 线程及同步一

一、并行执行规模 CUDA关于并行执行具有分层结构。每次内核启动时可以被切分成多个并行执行的块&#xff0c;而每个块又可以进一步地被切分成多个线程。这种并行执行的副本可以通过两种方式完成&#xff1a;一种是启动多个并行的块&#xff0c;每个块具有1个线程&#xff1b;另…

项目实战之旅游网(五)后台角色管理(下) 后台权限管理

目录 一.后台角色管理&#xff08;下&#xff09; 1.查询角色权限 2.修改角色权限 3.优化侧边栏菜单 二.后台权限管理 1.权限列表 2.新增权限 3.修改权限 4.删除权限 一.后台角色管理&#xff08;下&#xff09; 1.查询角色权限 先新建一个bean类型的实体类&#xf…

单商户商城系统功能拆解53—数据分析

单商户商城系统&#xff0c;也称为B2C自营电商模式单店商城系统。可以快速帮助个人、机构和企业搭建自己的私域交易线上商城。 单商户商城系统完美契合私域流量变现闭环交易使用。通常拥有丰富的营销玩法&#xff0c;例如拼团&#xff0c;秒杀&#xff0c;砍价&#xff0c;包邮…

一文清晰带你弄清楚Spring IOC 循环依赖问题是如何解决的

什么是循环依赖 循环依赖又被成为循环引用,即两个或者多个bean相互之间的持有对方,比如A 引用B,B引用C,C 又引用A,则它们最终反映为一个环,如下图所示: 循环依赖是对象之间的相互依赖关系,循环依赖就是一个死循环,除非有终结条件,否则就是死循环,最终导致内存溢出错误. 解决…