超深入了解掌握迭代器的知识点
目录
🗣️引言
🗣️小结
🗣️引言
假如给了你一个列表 lis = [1,2,3,4],叫你读取列表中的数据,那要如何做?
首先我们想到的是可能是索引读法,比如要读列表中的第二个元素可以用 lis[1]来读到,
其次那就是可以用最最常用的for循环来读取数据了,其中for循环的取值方式想必大家都应该也必须知道了,那就是———按顺序依次取值,既不关心取到的每一个值的位置,也不会跳过某一个值去取其他位置上的值。那此时想必你心中会有一个疑问那就是for循环为什么会这样取值,在for循环的内部究竟有哪一股神秘的代码驱使它这样工作呢?看完下面内容想必就有了答案!
带着这个疑问我们就来接触一下迭代器吧
-
⚛️可迭代的
👥一、for循环针对的数据类型特点
在开始前我们先了解两个英语单词
其次我们再看下面这两段代码
第一段:我们先将一个列表进行for循环,得到以下结果
第二段:换个思路我们将列表替换为数字2345那么结果会是什么呢?
输出结果:
结果竟然是报错:那我们再看报错内容的翻译:
它说int对象是不可迭代的,那么我们现在应该了解到了能够使用for循环的数据类型应该要是可迭代的,那么究竟哪些数据类型时可迭代的呢,我们应该如何区分呢?
👥二、可迭代的与可迭代协议
👤1、迭代的概念
将一个数据集中所有的数据按照顺序“一个接着一个一次取出”这个过程就叫做迭代
👤2、认识dir内置函数和双下方法
- dir内置函数:
python中的dir()函数dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。简而言之dir可以告诉我们所传入的数据类型(参数)所包含的所有内置使用方法
输出结果:
- 双下方法:
概念:像'__add__', '__class__', '__contains__'等含有双下划线的方法叫做双下方法
首先我们知道让两个列表相加的方法是:
其实还可以这样写:
这两者的联系是:其实在函数运行时并不认识"+,- ,* , /"号,因为程序只认识代码,所以你使用"+"时号程序内部会自动帮你调用"__add__"这个函数方法。
👤3、 如何证明一个数据类型是可迭代的
要证明一个数据类型是否是可迭代的我们要用到collections.abc模块
其中可迭代的数据类型是:list、dic、str、set、range()、f = open()、enumerate
找出这些数据类型的公共内置使用方法发现都有'__iter__',可得出结论:含有'__iter__'内置方法的数据是可迭代的(iterable)。
下面就是用集合的去重性找出这些数据类型的公共内置使用方法:
👤4、可迭代协议
Python 迭代协议由__iter__方法与__next__方法构成,若对象具有__iter__方法,称该对象为“可迭代对象(iterable object)”也就是可跌代的。若对象具有__next__方法,称该对象为“迭代器(iterator)”。__iter__方法必须返回一个迭代器对象,__next__方法不断的返回下一元素,或者抛出StopIteration。__next__方法是 Python 迭代协议的核心,__iter__方法是迭代协议的辅助——将可迭代对象转换成迭代器。
在大多数情况下,可迭代对象会自动转换成迭代器,迭代操作本质是由“迭代器”负责——每次迭代输出一个元素,当无元素时,会抛出StopIteration。这种自动转换机制是造成“可迭代对象”与“迭代器“概念模糊的主要原因。 另一造成混淆的原因就是,对象即是可迭代对象,也是迭代器——当对象具有__iter__方法与__next__方法,并且__iter__方法返回自身,一个典型对象就是“文件对象”。
我们可以用上面的dir方法判断数据类型内部是否含有__iter__方法,代码如下:
👤5、拓展点:内置enumerate函数的用法
可能会疑问enumerate怎么用使用方法如下:
enumerate()是python的内置函数 enumerate在字典上是枚举、列举的意思 对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值 enumerate多用于在for循环中得到计数 例如对于一个seq,得到: (0, seq[0]), (1, seq[1]), (2, seq[2])
enumerate()返回的是一个enumerate对象
使用方法如下:
输出结果:
👤6、总结可迭代的知识点
总结一下我们现在所知道的:可以被for循环的都是可迭代的,要想可迭代,内部必须有一个__iter__方法。
那么内部的__iter__方法做了什么事情呢?
执行了list([ ])的__iter__方法,我们好像得到了一个list_iterator,翻译后就是列表迭代器。
这下就明白了一个可迭代对象通过调用内部的__iter__方法就会变成一个迭代器
-
⚛️迭代器
👥一、迭代器协议
迭代器协议:
迭代器协议---内部含有__next__和__iter__方法的就是迭代器
从上面我们知道了一个可迭代对象通过调用内部的__iter__方法就会变成一个迭代器
[].__iter__()就是一个列表迭代器
我们来看看这个列表的迭代器比起列表来说实现了哪些新方法,这样就能揭开迭代器的神秘面纱了吧?
由上面我们知道,迭代器比原类型多出来了{'__setstate__', '__length_hint__', '__next__'}方法,这就是迭代器的秘密
👥二、迭代器秘密方法的使用
上面我们知道迭代器比原类型多出来了{'__setstate__', '__length_hint__', '__next__'}方法
那么这些方法有什么用呢?
这三个方法中,能让我们一个一个取值的神奇方法是谁?没错!就是__next__
在for循环中,就是在内部调用了__next__方法才能取到一个一个的值。
那接下来我们就用迭代器的next方法来写一个不依赖for的遍历。
输出结果:
为什么会报错呢?
如果我们一直取next取到迭代器里已经没有元素了,就会抛出一个异常StopIteration,告诉我们,列表中已经没有有效的元素了。
这个时候,我们就要使用异常处理机制来把这个异常处理掉。
👥三、迭代器协议的验证
上面说迭代器协议---内部含有__next__和__iter__方法的就是迭代器
用以下代码验证
👥四、验证range()是可迭代对象还是迭代器
👥五、迭代器的好处
迭代器的好处:
- 从容器类型中一个一个取值,会把所有的值都取到。
- 节省内存空间
迭代器并不会在内存中在占用一大块内存 而是随着循环每次生成一个
每一次next每次给我一个
👥六、迭代器总结
迭代器的概念
迭代器协议---内部含有__next__和__iter__方法的就是迭代器
迭代器协议和可迭代协议
可以被for循环的都是可迭代的
可迭代的内部都有__iter__方法
只要是迭代器 一定可迭代
可迭代的.__iter__()方法就可以的到一个迭代器
迭代器中的.__next__()方法可以一个一个的获取值
for循环实际上就是在使用迭代器
iterator 可迭代对象
直接给你内存地址
可迭代对象是与for循环挂钩,而迭代器是与next()函数挂钩的
🗣️小结
1、双下方法:__iter__,__next__很少直接调用的方,一般情况下是通过其他语法触发(for) 2、可以被for循环的都是可迭代的 3、可迭代的内部都有__iter__方法 4、只要是迭代器 一定可迭代 5、可迭代的.__iter__()方法就可以的到一个迭代器 6、迭代器中的.__next__()方法可以一个一个的获取值 7、for循环实际上就是在使用迭代器 迭代器的特点: 1、很方便使用,且只能取所有的数据取一次 2、节省内存空间
- 点赞
- 收藏
- 关注作者
评论(0)