-
2020-05-31 16:42:11
迭代的概念
上一次输出的结果为下一次输入的初始值,重复的过程称为迭代,每次重复即一次迭代,并且每次迭代的结果是下一次迭代的初始值
什么是迭代
- 访问集合元素的一种方式
- 可通过 for 循环遍历的对象 叫可迭代对象
- 数字类型 不可迭代
判断对象是否可迭代: isinstance( ) 判断是否为 Iterable(可迭代对象)
from collections.abc import Iterable #print(isinstance(要判断的对象,数据类型)) print(isinstance([1,2,3,4],Iterable)) 是可迭代对象 返回 True 不是可迭代对象 返回 False
可迭代的对象
内置iter方法的,都是可迭代的对象。 list是可迭代对象,dict是可迭代对象,set也是可迭代对象。
迭代器 Iterator
1.为什么要有迭代器?
对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式。2.迭代器定义:
迭代器:可迭代对象执行iter方法,得到的结果就是迭代器,迭代器对象有next方法它是一个带状态的对象,他能在你调用next()方法的时候返回容器中的下一个值,任何实现了iter和next()方法的对象都是迭代器,iter返回迭代器自身,next返回容器中的下一个值, 如果容器中没有更多元素了,则抛出StopIteration异常
迭代器的遍历循环:
class MyIterator(object): def __init__(self,list): self.list=list self.xiabiao=0 def __iter__(self): #获取迭代器,自身就为迭代器,所以返回自身 return self def __next__(self): #获取迭代器中的下一个数据 if self.xiabiao < len(slef.list): item=self.list[self.xiabiao] self.xiabiao += 1 return item else: raise StopIteration #抛出 停止迭代异常 a=[11,22,33,44,55] my=MyIterator(a) for i in my: print(i)
for…in… 循环的本质:
先通过iter( )获取可迭代对象的迭代器,然后对获取到的迭代器 不断使用next( )方法来获取下一个值,并赋值给一个变量,当遇到 StopIteration 循环结束while True: try: print(next( )) except StopIteration: break
迭代器的应用场景: 斐波那契数列
class Fei(object): def __init__(self,n): self.n=n self.weizhi=0 记录位置 self.num1=0 定义初始变量 self.num2=1 def __iter__(self): 获取迭代器,此类本身就是迭代器,返回自身 return self def __next__(self): 获取迭代器中的下一个数据 if self.weizhi < self.n: num=self.num1 self.num1,self.num2=self.num2,self.num1+self.num2 self.weizhi += 1 return num else: raise StopIteration fei=Fei(10) for i in fei: print(i)
查看迭代器数据的三种方法: for 、list、tuple
#for for i in fei: print(fei) #list print(list(fei)) #tuple print(tuple(fei))
生成器 generator
1.定义
- 生成器(generator)是一个特殊的迭代器,它的实现更简单优雅,yield是生成器实现next()方法的关键。它作为生成器执行的暂停恢复点,可以对yield表达式进行赋值,也可以将yield表达式的值返回。
- 也就是说,yield是一个语法糖,内部实现支持了迭代器协议,同时yield内部是一个状态机,维护着挂起和继续的状态。
- 生成器可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他数据类型需要调用自己的内置iter方法)
- 在Python中,一边循环,一边计算的机制,称为生成器。
yield的功能:
- 相当于为函数封装好iter和next
- return只能返回一次值,函数就终止了,而yield能返回多次值,每次返回都会将函数暂停,下一次next会从上一次暂停的位置继续执行
- 保存当前运行状态,暂停执行
- 将 yield 关键字 后面表达式的值,作为返回值返回,可理解为起到了return的作用
生成器的作用
- 通过列表生成式,我们可以直接创建一个列表,但是,受到内存限制,列表容量肯定是有限的。
- 而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
- 所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?
- 这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
生成器工作原理
-
生成器是这样一个函数,它记住上一次返回时在函数体中的位置。
-
对生成器函数的第二次(或第 n 次)调用跳转至该函数中间,而上次调用的所有局部变量都保持不变。
-
生成器不仅“记住”了它数据状态;生成器还“记住”了它在流控制构造中的位置。
-
生成器是一个函数,而且函数的参数都会保留。
-
迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的
yield生成器运行机制
在Python中,yield就是这样的一个生成器。- 当你问生成器要一个数时,生成器会执行,直至出现 yield 语句,生成器把yield 的参数给你,之后生成器就不会往下继续运行。
- 当你问他要下一个数时,他会从上次的状态开始运行,直至出现yield语句,把参数给你,之后停下。如此反复
- 在python中,当你定义一个函数,使用了yield关键字时,这个函数就是一个生成器
- 它的执行会和其他普通的函数有很多不同,函数返回的是一个对象,而不是你平常所用return语句那样,能得到结果值。如果想取得值,那得调用next()函数
- 每当调用一次迭代器的next函数,生成器函数运行到yield之处,返回yield后面的值且在这个地方暂停,所有的状态都会被保持住,直到下次next函数被调用,或者碰到异常循环退出。
为什么说生成器是一种迭代器?
Python 判断一个对象是否是迭代器的标准是看这个对象是否遵守迭代器协议 ,判断一个对象是否遵守迭代器协议主要看两个方面:- 对象首先得实现 iter 和 next 方法
- 其次iter 方法必须返回它自己
而生成器恰好满足了这两个条件(可以自己写个生成器,然后调用生成器的这两个方法试试)。我们平常还会经常碰到另外一个概念:可迭代对象。可迭代对象就是可迭代的对象,可迭代的对象就是说我们可以从这个对象拿到一个迭代器。在 Python 中,iter 方法可以帮我们完成这个事情,也就是说,可迭代对象和迭代器满足这样一个关系:iter(iterable) -> iterator。
在 Python 中,list 是个可迭代对象,所以我们经常会写这样的代码:
l = [1, 2, 3] for element in l: print(element)
但你想过为什么我们可以这么写吗?为啥在 c 语言里面,我们访问数组元素的时候,必须要通过 index?
因为:list 是个可迭代对象,我们在 Python 中使用 for … in 时,Python 会给我们生成一个迭代器对象,而如上所说:迭代器是个数据流,它可以产生数据,我们一直从里面取数据就好了,而不需要我们在代码中维护 index,Python 已经通过迭代器给我们完成了这个事情。
构建生成器:
将列表推导式的方括号 改为 小括号g=(i for i in range(1,11)) print(g)
使用 yield
构建斐波那契数列def fei(n): num1,num2=0,1 weizhi=0 while weizhi < n : num=num1 num1,num2=num2,num1+num2 weizhi += 1 yield num print(list(fei(10)))
唤醒生成器:
send( )、next( )、 __next__( )
send( ) ret=fei(10) a=ret.send(None) print(a) next( ) ret=fei(10) while True: try: print(next(ret)) except StopIteration: break
生成器和迭代器之间的区别
在使用生成器时,我们创建一个函数;在使用迭代器时,我们使用内置函数iter()和next()。 在生成器中,我们使用关键字‘yield’来每次生成/返回一个对象。 生成器中有多少‘yield’语句,你可以自定义。 每次‘yield’暂停循环时,生成器会保存本地变量的状态。而迭代器并不会使用局部变量,它只需要一个可迭代对象进行迭代。 使用类可以实现你自己的迭代器,但无法实现生成器。 生成器运行速度快,语法简洁,更简单。 迭代器更能节约内存。
更多相关内容 -
〖Python零基础入门篇(61)〗- Python 中的迭代器
2022-04-01 00:35:07该章节我们来学习一下 Python 中的一个新的概念,那就是 迭代器 。迭代器的使用可以帮助我们提升代码的性能,接下来让我们看一下关于迭代器,我们需要学习一下哪些内容。万叶集 🎉 隐约雷鸣,阴霾天空。 🎉 🎉 但盼风雨来,能留你在此。 🎉
前言:
✌ 作者简介:渴望力量的哈士奇 ✌,大家可以叫我 🐶哈士奇🐶 ,一位致力于 TFS 赋能的博主 ✌
🏆 CSDN博客专家认证、新星计划第三季全栈赛道 top_1 、华为云享专家、阿里云专家博主 🏆
📫 如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀
💬 人生格言:优于别人,并不高贵,真正的高贵应该是优于过去的自己。💬
🔥 如果感觉博主的文章还不错的话,还请👍关注、点赞、收藏三连支持👍一下博主哦
专栏系列(点击解锁) 学习路线指引 知识定位 🔥Python全栈白皮书🔥 零基础入门篇 以浅显易懂的方式轻松入门,让你彻底爱上Python的魅力。 语法进阶篇 主要围绕多线程编程、正则表达式学习、含贴近实战的项目练习 。 自动化办公篇 实现日常办公软件的自动化操作,节省时间、提高办公效率。 自动化测试实战篇 从实战的角度出发,先人一步,快速转型测试开发工程师。 数据库开发实战篇 更新中 爬虫入门与实战 更新中 数据分析篇 更新中 前端入门+flask 全栈篇 更新中 django+vue全栈篇 更新中 拓展-人工智能入门 更新中 网络安全之路 踩坑篇 记录学习及演练过程中遇到的坑,便于后来居上者 网安知识扫盲篇 三天打鱼,不深入了解原理,只会让你成为脚本小子。 vulhub靶场漏洞复现 让漏洞复现变得简单,让安全研究者更加专注于漏洞原理本身。 shell编程篇 不涉及linux基础,最终案例会偏向于安全加固方向。 [待完结] WEB漏洞攻防篇 2021年9月3日停止更新,转战先知社区等安全社区及小密圈 渗透工具使用集锦 2021年9月3日停止更新,转战先知社区等安全社区及小密圈 点点点工程师 测试神器 - Charles 软件测试数据包抓包分析神器 测试神器 - Fiddler 一文学会 fiddle ,学不会倒立吃翔,稀得! 测试神器 - Jmeter 不仅是性能测试神器,更可用于搭建轻量级接口自动化测试框架。 RobotFrameWork Python实现的自动化测试利器,该篇章仅介绍UI自动化部分。 Java实现UI自动化 文档写于2016年,Java实现的UI自动化,仍有借鉴意义。 MonkeyRunner 该工具目前的应用场景已不多,文档已删,为了排版好看才留着。
什么是迭代器
迭代是
python
中访问集合元素的一种非常强大的一种方式。迭代器是一个可以记住遍历位置的对象
,因此不会像列表那样一次性全部生成,而是可以等到用的时候才生成,因此节省了大量的内存资源。迭代器对象从集合中的第一个元素开始访问,直到所有的元素被访问完。迭代器有两个方法:iter()
和next()
方法。这么解释可能不太直观,我们以生活的一个小栗子来解释一下,方便大家能够更深刻的理解。比如说我们去超市买水果,而正巧超市的服务人员正在摆放苹果。服务人员告诉我们需要等苹果都摆放完毕我们才可以拿苹果,这样就很耽误我们的时间。(这个场景中,柜台上其实已经有苹果了,只不过销售不让拿罢了。)
然后我们再去卖橘子的柜台,服务人员也在摆放橘子。但是服务人员告诉我们可以不用等他摆放完毕,我们可以直接拿橘子,这样就会很好的节省我们的时间。如果我们拿橘子的速度超过了服务人员摆放的速度 ,我们只需要等待服务人员摆放之后就可以直接拿橘子,大大的提升了我们买橘子的效率。
而迭代器就类似于我们买橘子的场景,我们平时的程序都是一次性写入到内存中。比如我们的列表中存在成百上千的数据,都是一次性写入到内存里的,通过这样让我们来使用。但是迭代器却是按需加载,有一点内容就会放在内容里面,我们就可以立刻使用内存中的数据进行我们的逻辑处理。这样就不要所有的数据都写入到内存中就可以使用,大大的提升了使用效率。
如何生成迭代器
迭代器函数 - iter() 函数 与 next() 函数
iter(iterable)从可迭代对象中返回一个迭代器,iterable必须是能提供一个迭代器的对象 next(iterator) 从迭代器iterator中获取下一了记录,如果无法获取下一条记录,则触发stoptrerator异常 说明: 1.迭代器只能往前取值,不会后退 2.用iter函数可以返回一个可迭代对象的迭代器 示例:
iter()函数介绍:生成一个迭代器对象
iter()函数用法:iter(iterable)
参数介绍:iterable —> 可迭代的数据类型(比如列表、字典、元组以及集合类型等)
示例:iter([1, 2, 3])
返回值:<list_iterator at 0x4f3bff0>
next()函数介绍:返回迭代器中的数据
next()函数用法:next(iterable)
参数介绍:iterable —> 迭代器对象
示例:
iter_obj = iter([1,2,3]) next(iter_obj)
返回值:
# >>> 1,2,3 # >>> StopIteration
综上,我们得出结论:
iter(iterable)从可迭代对象中返回一个迭代器,iterable必须是能提供一个迭代器的对象
next(iterable) 从迭代器iterator中获取下一了记录,如果无法获取下一条记录,则触发stoptrerator异常演示案例如下:
# coding:utf-8 test_list = [1, 3, 5, 7] test_iter = iter(test_list) # 让test_list提供一个能访问自己的迭代器 print(next(test_iter)) # 1 从迭代器中取值,让迭代器去获取l中的一个元素 print(next(test_iter)) # 3 print(next(test_iter)) # 5 print(next(test_iter)) # 7 print(next(test_iter)) # StopIterable 异常
test_list 实际上是一个列表,但是被迭代器迭代之后。并不是一次性将列表放入内存中,而是每次放一个元素进入内存,然后被读取。(这就是我们说的按需加载)
可迭代的对象
类似于
list、tuple、str
等类型的数据可以使用for… in…
的循环遍历语法可以从其中依次拿到数据并进行使用,我们把这个过程称为遍历,也称迭代。python中可迭代的对象有list(列表)、tuple(元组)、dirt(字典)、str(字符串)set(集合)
等。示例如下:
test_list = [1,2,3,4,5] test_dirt = { "name":"张三", "sex":"男", "age":33 } test_tuple = (1,2,3,4,5) test_set = {1,2,3,3,4} for i in test_list: print(i) for i in test_dirt: print(i) for i in test_tuple: print(i) for i,j in test_set.items(): print("%s:%s" % (i,j)) # >>> 执行结果如下: # >>> test_list的元素为: 1 # >>> test_list的元素为: 2 # >>> test_list的元素为: 3 # >>> test_list的元素为: 4 # >>> test_list的元素为: 5 # >>> test_dirt的元素为: name # >>> test_dirt的元素为: sex # >>> test_dirt的元素为: age # >>> test_tuple的元素为: 1 # >>> test_tuple的元素为: 2 # >>> test_tuple的元素为: 3 # >>> test_tuple的元素为: 4 # >>> test_tuple的元素为: 5 # >>> test_set的元素为:1 # >>> test_set的元素为:2 # >>> test_set的元素为:3 # >>> test_set的元素为:4
生成迭代器
除了刚刚我们使用的 iter() 函数之外
,我们还有其他方法生成迭代器:第一种:for循环生成方法 —> 我们可以在函数中使用 for 循环, 并对每一个 for 循环的成员使用 yield() 函数 [它的意思就是将每一个 for 循环成员放到一个迭代器对象中,不过只有被调用才会被放入。]
示例如下:
def test(): for i in range(10): yield i result = test() print('for 循环,第一次 \'i\'的值为:', next(result)) print('for 循环,第二次 \'i\'的值为:', next(result)) print('for 循环,第三次 \'i\'的值为:', next(result)) print('for 循环,第四次 \'i\'的值为:', next(result)) # >>> 执行结果如下: # >>> for 循环,第一次 'i'的值为: 0 # >>> for 循环,第二次 'i'的值为: 1 # >>> for 循环,第三次 'i'的值为: 2 # >>> for 循环,第四次 'i'的值为: 3
注意:超过10次异常会抛
StopIteration
的异常。
第二种:for 循环一行生成迭代器对象。
示例如下:
result = (i for i in [1, 2, 3]) # 将 for 循环在非函数中 赋值 给一个变量, 这也是生成一个迭代器变量的方法 print('for 循环,第一次 \'i\'的值为:', next(result)) # 使用 next 调用迭代器 print('for 循环,第二次 \'i\'的值为:', next(result)) print('for 循环,第三次 \'i\'的值为:', next(result)) # >>> for 循环,第一次 'i'的值为: 1 # >>> for 循环,第二次 'i'的值为: 2 # >>> for 循环,第三次 'i'的值为: 3
注意:
next(result)
超过4次会抛StopIteration
的异常。划重点:
使用 for 循环生成的迭代器,可以不使用
next() 函数
也可以执行,(依然可以通过 for 循环 获取迭代器的数据)不仅如此,当我们调取完迭代器中的数据之后,程序不会抛出异常,相比较与 next() 函数要友好的多。
示例如下:
result = (i for i in [1, 2, 3]) for item in result: print(item) # >>> 执行结果如下: # >>> 1 # >>> 2 # >>> 3 # 循环结束,程序正常退出,不会抛出 StopIteration 的异常
迭代器的用法 - 演示案例
案例一:
def make_iter(): for i in range(5): yield i iter_obj = make_iter() for i in iter_obj: print(i) print('----') for i in iter_obj: print(i) # >>> 执行结果如下: # >>> 0 # >>> 1 # >>> 2 # >>> 3 # >>> 4 # >>> ---- # >>> 从运行结果得出结论,当我们从内存中读取完迭代器所有的值后,内存就会被释放,不再循环输出。
案例二:
iter_obj = (i for i in range(4)) for i in iter_obj: print(i) print('=====') for i in iter_obj: print(i) # >>> 执行结果如下: # >>> 0 # >>> 1 # >>> 2 # >>> 3 # >>> ===== # >>> 从运行结果得出结论,当我们从内存中读取完迭代器所有的值后,内存就会被释放,不再循环输出。
迭代器
除了前文我们提到的按需加载
,可以提升我们的执行速度以外。还有另外一个原因,试想一下:如果我们的列表只有10个数据,那么读取的速度会很快。可能对资源(也就是我们的内存)占用的消耗不是很大;如果我们有一个成千上万甚至十万数据的列表,那么这些数据都要一次性的写入内存里,这么多的数据所消耗占用的资源必然会很大,甚至会撑爆我们的内存造成内存溢出,程序就会报错了。
所以如果通过迭代器的方式,我们只需要用到一个数据就将一个数据扔到内存里并且被使用。这样既可以提高我们内存使用的效率,又可以减少我们内存的消耗。
这也是我们平时使用迭代器的目的。
-
C++中STL各个迭代器详解
2019-04-01 23:04:541、自C++11起可以用range-based for循环来所有元素,但有时并不需要处理所有元素,此时可以使用迭代器。 std::vector<int> vec {1,2,3,4,5,6,7,8,9,10};...2、迭代器中用来表现容器中的某个位置 oper...1、自C++11起可以用range-based for循环来所有元素,但有时并不需要处理所有元素,此时可以使用迭代器。
std::vector<int> vec {1,2,3,4,5,6,7,8,9,10}; for (auto n : vec){ std::cout << n << endl; }
2、迭代器中用来表现容器中的某个位置
- operator * :返回当前位置上的原始值。如果该元素拥有成员,可用-->取用他它们。
- operator ++ :返回当前位置上的元素值,有些迭代器还可以使用operator ——退至前一元素。(注:“前置++”比“后置++”效率高)
- operator == 和 !=:判断两个迭代器是否指向同一位置。
- operator = :对迭代器赋值。
3、容器的begin()和end()
begin():返回一个迭代器,指向容器终点,即第一个元素(如果有的话)的位置。
end():返回一个迭代器,指向容器终点。终点位于最末元素的下一位置,又称“逾尾迭代器”。
4、range-based for循环VS迭代器
对容器而言rang-based for循环不过是个便捷接口,用来迭代它“所接收到的几何区间”内每一个元素。在循环体内,真实元素被“当前迭代器所指向的value”初始化。
(1)range-based for循环
for (type elem : coll){
...
}
(2)迭代器
for(auto pos = coll.begin(), end = coll.end(); pos != end; ++pos+){
type elem = *pos;
...
}
5、迭代器的种类
(1)前向迭代器(Forward iterator) 只能够以累加操作符(increment operator) 向前迭代。
Class forward _list的迭代器就属此类。其他容器如unordered_ set、 unordered_multiset、 unordered_map和unordered_multimap 也都至少是此类别(但标准库其实为它们]提供的是双向迭代器[forward iterator]。
(2)双向迭代器(Bidirectional iterator)顾 名思义它可以双向行进:以递增(increment)运算前进或以递减(decrement) 运算后退。list. set、 multiset、 map 和multimap提供的迭代器都属此类。
(3)随机访问迭代器(Random-access iterator)它 不但具备双向迭代器的所有属性,还具备随机访问能力。更明确地说,它们提供了迭代器算术运算的必要操作符(和寻常指针的算术运算完全对应)。你可以对迭代器增加或减少- - 个偏移量、计算两迭代器间的距离,或使用<和>之类的relational (相对关系)操作符进行比较。vector, deque.array和string提供的迭代器都属此类。除此之外,STL还定义了两个类别:
●输入型迭代器(Input iterator) 向前选代时能够读取/处理value。 Input stream迭代器就是这样-一个例子。
●输出型迭代器(Output iterator) 向前迭代时能够涂写value。 Inserter 和output stream迭代器都属此类。
6、具体迭代器
(1)output迭代器
a、output迭代器允许一步一步前行并搭配writ动作。
可以一个一个元素地赋值,但不能使用output迭代器对同一区间迭代两次。无比较操作,无法检验output迭代器是否有效,或写入是否成功。
b、output迭代器的操作
c、通常,迭代器可用来读,也可用来写,几乎所有reading迭代器都有write 的额外功能,这种情况下它们]被称为mutable (可产生变化的)迭代器。
一个典型的pure output迭代器例子是:“将元素写至标准输出设备(例如屏幕或打印机)”。如果采用两个output迭代器写至屏幕,第二个字将跟在第一个字后面,而不是覆盖(overwrite)第一个字。另一个典型例子是inserter,那是一种用 来将value 插入(insert) 容器内的迭代器:如果你赋值(assign) 一个value,你其实是将它插入(insert) 容器。如果随后写入第二个value,并不会覆盖第一个 value,而是安插进去。
(2)input迭代器
a、input迭代器只能一次一个以前行方向读取元素,按此顺序一个一个返回元素值。
input迭代器只能读取元素。如果复制input迭代器,并令input迭代器和新产生的拷贝都前向读取,可能会有不同的值。
b、input迭代器的操作
c、所有迭代器都具备input迭代器的能力,而且往往更强。Pure input迭代器的典型例子就是“从标准输人设备(往往是键盘)读取数据”。同一个值不会被读取两次。一旦从input stream读人一个字(离开input缓冲区),下次读取时就会返回另一一个字。
(3)forward(前向)迭代器
a、forward迭代器是一种input迭代器且在前进读取时提供额外保证。
b、forward迭代器的操作
(4)bidirectional(双向)迭代器
a、bidirectional迭代器是在 forward迭代器的基础上增加了回头迭代器能力。
b、bidirectional迭代器新增操作
c、bidirectional迭代器由一下对象和类型提供:
- Class list<>
- Associative (关联式)容器。
如果bidirectional迭代器履行了output迭代器立有的条件,那么它就是个mutable bidirectional迭代器,既可用于读取,也可用于涂写。
(5)Random-Access(随机访问)迭代器
a、random-access迭代器是在bidirectional迭代器的基础上增加了随机访问的能力。因此它能提供iterator算术运算,即它能增减某个偏移量、计算距离,并运诸如<和>等关系操作符进行比较。
b、random-access迭代器的新增的操作
d、random-access迭代器提供者:
- 可随机访问的容器(array、vector、deque)
- String(string、wstrin)
- 寻常的C-style array(pointer)
注:在使用的时候注意迭代器指向的位置,特别是一些特殊的位置,比如begin()前面,或者end()后面则会产生越界。
7、迭代器相关辅助函数
(1)advance()
a、advance()课件迭代器的位置增加,增加幅度由实参决定,即它令迭代器一次前景(或后退)多个元素。
b、#include<iterator>
void advance (InputIterator& pos, Dist n)
●令名称为pos的 input迭代器前进(或后退) n个元素。
●对bidirectional迭代器和random-access迭代器而言,n可为负值,表示向后退。
●Dist是个 template类型。通常它必须是个整数类型,因为会调用诸如<. ++. -- 等操作,还要和0做比较。
●advance() 并不检查迭代器是否超过序列的end() (因为迭代器通常不知道其所操作的容器,因此无从检查)。所以,调用advance()有可能导致不明确行为--因为 “对序列尾端调用operator++"是一种未被定义的行为。
(2)next()和prev()
a、用于前进和后退移动迭代器的位置
b、next()
#include<iterator>
ForwardIterator next(ForwardIterator pos)
ForwardIterator next(ForwardIterator pos, Dist n)
●导致 forward迭代器pos前进1或n个位置。
●如果 处理的是bidirectional和random-access迭代器,n可为负值,导致后退(回头)移 动。
●Dist是类型std: :iterator _traits<ForwardIterator>: :difference. type。●其内部将对一个临时 对象调用advance (pos,n)。
●注意,next()并不检查是否会跨越序列的end()。 因此调用者必须自行担保其结果有效。
c、prev()
BidirectionalIterator prev(BidirectionalIterator pos)
BidirectionalIterator prev(BidirectionalIterator pos, Dist n)
●导致 bidrctional迭代器pos后退1或n个位置。
●n可为负值,导致向前移动。
●Dist是类型std::iterator. traits<BidirectionalIterator>: :difference_type。
●其内部将对一个临时对象调用advance(pos, -n)。
●注意,prev()并不检查是否会跨越序列的begin()。因此调用者必须自行担保其结果有效。注:next()和prev()始自C++11,因此若以operator++和--取而代之,有可能无法针对每一种容器都通过编译。
(3)distance()
a、distance()用来处理两个迭代器之间的距离
b、#include<iterator>
Dist distance (InputIterator pos1, InputIterator pos2)
●返回两个input迭代器posI和pos2之间的距离。
●两个迭代器必须指向同一个容器。
●如果不是random-access迭代器,则从pos1开始前进必须能够到达pos2, 亦即pos2的位置必须与posl相同或在其后。
●返回类型Dist是迭 代器相应的difference类型:
iterator_ traits<InputIterator>: :difference_ type
(4)iter_swap()
a、iter_swap()这个辅助函数用来交换两个迭代器所指的元素值
b、#include<algorithm>
void iter_swap(ForwardIterator1 pos1, ForwardIterator2 pos2 )
- 交换迭代器pos1和pos2所指的值
- 迭代器的类型不必相同,但其所指的两个值必须可以互相赋值
8、迭代器适配器
(1)反向迭代器
反向处理元素
例:
void print(int elem) { cout << elem << ' '; } int main() { list<int> coll = { 1, 2, 3, 4, 5 }; for_each(coll.begin(), coll.end(), print); cout << endl; for_each(coll.rbegin(), coll.rend(), print); cout << endl; system("pause"); return 0; }
输出:
注:rebegin():逻辑位置是从最后一个位置的后一个位置起算的,但其物理位置为他的前面一位。
rend():指针逻辑位置为第一位,物理位置为第一位的前面一位(有时候并不存在)。
注:foreach()
函数原型:
template<typename InputIterator, typename Function> Function for_each(InputIterator beg, InputIterator end, Function f) { while(beg != end) f(*beg++); }
b、迭代器和反向迭代器
反向迭代器的逻辑位置和物理位置的值不一样。
(图1)反向迭代器的位置和其value(其所指元素值)的关系
(图2)迭代器pos和reverse(反向)迭代器rpos直接的转换
注:
reverse 迭代器的设计者运用了一个小技巧:他们实际倒置了“半开原则”。Reverse迭代器听定义的区间,并不包括起点,反倒是包括了终点。然而逻辑上其行为一如往常。这么一来reverse迭代器物理意义所指的元素位置,和逻辑意义所指的元素位置就不一致(如图1所示)。现在问题是,将一个迭代器转化为reverse迭代器,过程中发生了什么?该迭代器所保持(履行)的究竟是逻辑位置(value) 还是物理位置(element)? 从上面的例子可知,后者才是答案。因此,其value (也就是其所指元素值)也就移到了前一个元素身上(如图2所示)。
注:
以图2为例,当我们]把pos转换为rpos,它们指向同-一点,但它们所代表的意义(或说它们所代表的逻辑位置)不同了,*pos 为5,*rpos 则是4。换另一个角度看,如果你把[rbegin(), rend())形成的区间颠倒过来(把图上下颠倒看),你会发现其性质就和以[begin(), end()形成的区间完全- 样。
例:
vector<int> coll = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; vector<int>::const_iterator pos; for_each(coll.begin(), coll.end(), print); cout << endl; pos = find(coll.begin(), coll.end(), 5); cout << &pos << " pos: " << *pos << endl; vector<int>::const_reverse_iterator rpos(pos); for_each(coll.rbegin(), coll.rend(), print); cout << endl; cout << &rpos << " rpos: " << *rpos << endl;
输出:
注:find():返回第一次找到元素的位置
例:
#include<iostream> #include<deque> #include<deque> #include<algorithm> using namespace std; void print(int elem) { cout << elem << ' '; } int main() { deque<int> coll = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; deque<int>::const_iterator pos1; pos1 = find(coll.cbegin(), coll.cend(), 2); deque<int>::const_iterator pos2; pos2 = find(coll.cbegin(), coll.cend(), 7); for_each(pos1, pos2, print); cout << endl; // [pos1, pos2) deque<int>::const_reverse_iterator rpos1(pos1); deque<int>::const_reverse_iterator rpos2(pos2); for_each(pos1, pos2, print); cout << endl; system("pause"); return 0; }
输出:
c、运用base()将reserve迭代器转回正常
base()可以将reserve迭代器转回正常的迭代器
例:
vector<int> coll = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; vector<int>::const_iterator pos; pos = find(coll.begin(), coll.end(), 5); cout << "pos: " << *pos << endl; vector<int>::const_reverse_iterator rpos(pos); cout << "rpos: " << *rpos << endl; vector<int>::const_iterator rrpos; rrpos = rpos.base(); cout << "rrpos: " << *rrpos << endl;
(2)insert(安插型)迭代器
a、用来将“赋予新值”动作转换为“安插新值”动作。算法将执行安插行为而非覆写行为。
b、insert迭代器允许的操作
- operator *别实现为一个无作用的no-op,仅仅返回*this。所以对insert迭代器来说,*pos与pos等价。
- 赋值动作(assignment) 被转化为安插动作(insertion)。 事实上,insert 迭代器会调用容器的push. back()、push. .front()或insert()成员函数。
c、insert迭代器的中类
C++标准库提供三种insert迭代器: back inserter, front inserter和general inserter。它们之间的区别在于安插的位置。事实上,它们各自调用所属容器中不同的成员函数。所以insert迭代器初始化时- -定要清楚指明所属的容器是哪一种。
每一种insert迭代器都可以由一个对应的便捷函数加以生成和初始化。
注:容器本身要支持insert迭代器所调用的函数。back_insert只能用在vector、deque、list和string上,front_insert只能用在deque和list上。
例:back_insert_iterator
#include<iostream> #include<iterator> #include<vector> #include<algorithm> using namespace std; void print(int elem) { cout << elem << ' '; } int main() { vector<int> coll; back_insert_iterator<vector<int> > iter(coll); *iter = 1; iter++; *iter = 2; for_each(coll.begin(), coll.end(), print); cout << endl; back_inserter(coll) = 23; back_inserter(coll) = 65; for_each(coll.begin(), coll.end(), print); cout << endl; coll.reserve(2 * coll.size()); //注意在调用copy之前要保证有足够的空间 copy(coll.begin(), coll.end(), back_inserter(coll)); for_each(coll.begin(), coll.end(), print); cout << endl; system("pause"); return 0; }
输出:
注:general insert(insert_iterator)
根据两个实参完成初始化:容器;待安插的位置
general insert对所以容器适用(除array和forward list)
例:
#include<iostream> #include<set> #include<list> #include<algorithm> #include<iterator> using namespace std; void print(int elem) { cout << elem << ' '; } int main() { set<int> coll; insert_iterator<set<int> > iter(coll, coll.begin()); *iter = 1; iter++; *iter = 2; inserter(coll, coll.end()) = 66; inserter(coll, coll.end()) = 88; cout << "set: "; for_each(coll.begin(), coll.end(), print); cout << endl; list<int> coll2; copy(coll.begin(), coll.end(), inserter(coll2, coll2.begin())); cout << "list: "; for_each(coll2.begin(), coll2.end(), print); cout << endl; copy(coll.begin(), coll.end(), inserter(coll2, ++coll2.begin())); cout << "list: "; for_each(coll2.begin(), coll2.end(), print); cout << endl; system("pause"); return 0; }
输出:
(3)Stream(串流)迭代器
1)ofstream
Ostream迭代器可以将“被赋值”(assigned value)写人output stream.用了它,算法就可以直接写人stream.其实现机制与insert迭代器概念一致,唯一的区别在f ostream迭代器将赋值动作转化为output动作(通过operator<<)。 如此一来算法就可以使用寻常的选代器接口直接对stream执行涂写动作。
ostream 迭代器提供的各项操作:
例:
int main() { ostream_iterator<int> intWriter(cout, "\n"); *intWriter = 61; intWriter++; *intWriter = 88; vector<int> coll = { 1, 2, 3, 4, 5, 6 }; copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, "<")); cout << endl; return 0; }
输出:
2)istream
从input stream读取元素,注意可能读取会失败(读取到文件尾部,或读取失败),终点位置可以使用end-of-stream,只要任何一次读取失败,所以istream迭代器都会变成end-of-stream迭代器,所以进行一次读取后,应该将istream迭代器拿来和end-of-stream迭代器做比较,看此迭代器是否还有效。
操作如下:
如果满足一下条件则说明两个istream迭代器相等:
- 两者都是end-of-stream迭代器(因而不能再进行读取)或
- 两者都可以再进行读取,并指向相同的stream
例:
int main() { istream_iterator<int> intReader(cin); istream_iterator<int> intReaderEOF; while (intReader != intReaderEOF) { cout << "once: " << *intReader << endl; cout << "once again:" << *intReader << endl; ++ intReader; } return 0; }
读取到f(类型不匹配)时退出
例:
int main() { istream_iterator<int> cinPos(cin); ostream_iterator<int> coutPos(cout, "-->"); while (cinPos != istream_iterator<int>()) { advance(cinPos, 2); //跳过输入单元 if (cinPos != istream_iterator<int>()) //检查istream迭代器是否有效,防止越界 { *coutPos++ = *cinPos++; } } cout << endl; return 0; }
(4)move迭代器
以move迭代器取代copy,将元素从一个区间放到另一个区间。
例:
std::list<std::string> s; std::vector<string> v1(s.begin(), s.end()); // 把字符串s复制到v1 std::vector<string> v2(make_move_iterator(s.begin()), // 把字符串s移动到v2 make_move_iterator(s.end()));
一般而言,只有当“算法将元素从某个来源区间迁移(transfer) 至某个目标区间”,这种情况下在算法中使用move迭代器才有意义。此外,你必须确保每个元素只被处理- -次,否则,其内容将被搬移一次以上,那会导致不明确的行为。
注意,唯一保证“元素只被读取或被处理-次”的迭代器种类是input iterator。因此,通常只有当“某算法有个来源端,其内要求input iterator. 并且有个目的端,其内使用output iterator”,这时候使用move迭代器才有意义。唯例外是for. each(),它可处理波指明区间(passed range)内的被搬移元素(moved element),例如把它们搬移到一个新容器内。
-
C++迭代器操作
2019-03-09 10:54:35一、advance 头文件iterator template <class InputIterator, class Distance&...通过n个元素位置推进迭代器。 如果它是随机访问迭代器,则该函数仅使用一次operator +或operator-。 否则,该函数重复...一、advance
头文件iterator
template <class InputIterator, class Distance> void advance (InputIterator& it, Distance n);
推进迭代器
通过n个元素位置推进迭代器。如果它是随机访问迭代器,则该函数仅使用一次operator +或operator-。 否则,该函数重复使用增加或减少运算符(运算符++或运算符 - ),直到n个元素被提前。
参数
- it
迭代器要先进。
InputIterator至少应该是一个输入迭代器。 - n
要提前的元素位置数。
这对随机访问和双向迭代器只是负面的。
Distance应为能够表示此类迭代器之间距离的数值类型。
返回值
没有
// advance example #include <iostream> // std::cout #include <iterator> // std::advance #include <list> // std::list int main () { std::list<int> mylist; for (int i=0; i<10; i++) mylist.push_back (i*10); std::list<int>::iterator it = mylist.begin(); std::advance (it,5); std::cout << "The sixth element in mylist is: " << *it << '\n'; return 0; }
复杂度
随机访问迭代器的常量。
否则,线性为n。迭代器有效性
推进一个至少不是前向迭代器的输入迭代器可能会使从其值获得的任何迭代器,指针和引用无效。
数据范围
该函数修改迭代器,但它永远不会被解引用(调用不会访问指向对象)。
还要注意上面描述的对迭代器有效性的影响。异常
如果在迭代器上执行的任何算术运算抛出,则抛出,提供与此类操作相同的保证级别。
二、distance
template<class InputIterator> typename iterator_traits<InputIterator>::difference_type distance (InputIterator first, InputIterator last);
返回迭代器之间的距离
计算第一个和最后一个之间的元素数。如果它是随机访问迭代器,则函数使用operator-来计算它。 否则,该函数重复使用增量运算符(operator ++)。
参数
- first
迭代器指向初始元素。 - last
迭代器指向最后的元素。 这必须从一开始就可以到达。
InputIterator至少应该是一个输入迭代器。
返回值
第一个和最后一个之间的元素数量。
// distance example #include <iostream> // std::cout #include <iterator> // std::distance #include <list> // std::list int main () { std::list<int> mylist; for (int i=0; i<10; i++) mylist.push_back (i*10); std::list<int>::iterator first = mylist.begin(); std::list<int>::iterator last = mylist.end(); std::cout << "The distance is: " << std::distance(first,last) << '\n'; return 0; }
复杂度
随机访问迭代器的常量。
否则,线性为n。迭代器有效性
如果InputIterator不是至少一个前向迭代器,那么首先和任何迭代器,从其值获得的指针和引用可能会失效。
数据范围
该函数访问两个迭代器,但没有解除引用(调用不访问指向对象)。
还要注意上面描述的对迭代器有效性的影响。异常
如果在迭代器上执行的任何算术运算抛出,则抛出,提供与此类操作相同的保证级别。
三、begin
头文件iterator、array、deque、forward_list、list、map、regex、set、string、unordered_map、unordered_set、vector
【C++ 11】container (1) template <class Container> auto begin (Container& cont) -> decltype (cont.begin()); template <class Container> auto begin (const Container& cont) -> decltype (cont.begin()); array (2) template <class T, size_t N> T* begin (T(&arr)[N]);
迭代开始
返回指向序列中第一个元素的迭代器:(1)容器
该函数返回cont.begin()。
(2)数组
该函数返回其参数的数组到指针的转换。如果序列为空,则不应取消引用返回的值。
这些函数模板在多个头文件中定义:这些头文件中的每一个都包含所有容器和数组类型的通用模板,而不仅仅是特定的重载。 头文件是:<iterator>,<array>,<deque>,<forward_list>,<list>,<map>,<regex>,<set>,<string>,<unordered_map>,<unordered_set>和<vector>。
相反,<initializer_list>和<valarray>中的begin被重载(具有不同的定义)。
参数
- cont
定义了成员begin的类类型的对象。 - arr
数组。
返回值
对于(1),与cont.begin()返回的相同。
对于(2),指向数组中第一个元素的指针。数据范围
访问该参数但未修改。
调用不会访问序列中的任何元素,但返回的迭代器可用于访问或修改它们。异常
提供与对参数执行的操作相同级别的保证(对于标准容器和数组,这是一种无抛出保证)。
四、end
头文件iterator、array、deque、forward_list、list、map、regex、set、string、unordered_map、unordered_set、vector
【C++ 11】container (1) template <class Container> auto end (Container& cont) -> decltype (cont.end()); template <class Container> auto end (const Container& cont) -> decltype (cont.end()); array (2) template <class T, size_t N> T* end (T(&arr)[N]);
迭代器结束
返回指向序列中的past-the-end元素的迭代器:(1)容器
该函数返回cont.end()。
(2)数组
该函数返回arr + N.如果序列为空,则返回的值将与begin返回的值相等,并使用相同的参数。
这些函数模板在多个头文件中定义:这些头文件中的每一个都包含所有容器和数组类型的通用模板,而不仅仅是特定的重载。 标题是:<iterator>,<array>,<deque>,<forward_list>,<list>,<*map>*,<regex>,<set>,<string>,<unordered_map>,<unordered_set>和<vector>。
相反,在头<initializer_list>和<valarray>中,end被重载(具有不同的定义)。
参数
- cont
定义成员结束的类类型的对象。 - arr
数组。
返回值
对于(1),与cont.end()返回的相同。
对于(2),指向将跟随数组中最后一个元素的元素的指针。// std::begin / std::end example #include <iostream> // std::cout #include <vector> // std::vector, std::begin, std::end int main () { int foo[] = {10,20,30,40,50}; std::vector<int> bar; // iterate foo: inserting into bar for (auto it = std::begin(foo); it!=std::end(foo); ++it) bar.push_back(*it); // iterate bar: print contents: std::cout << "bar contains:"; for (auto it = std::begin(bar); it!=std::end(bar); ++it) std::cout << ' ' << *it; std::cout << '\n'; return 0; }
数据范围
访问该参数但未修改。
调用不会访问序列中的任何元素,但返回的迭代器可用于访问或修改它们。异常
提供与对参数执行的操作相同级别的保证(对于标准容器和数组,这是一种无抛出保证)。
五、prev
头文件iterator
template <class BidirectionalIterator> BidirectionalIterator prev (BidirectionalIterator it, typename iterator_traits<BidirectionalIterator>::difference_type n = 1);
获取前一个元素的迭代器
返回一个迭代器,指向如果高级-n位置它将指向的元素。如果它是随机访问迭代器,则该函数仅使用一次operator +或operator-。 否则,该函数在复制的迭代器上重复使用增加或减少运算符(operator ++或operator–),直到n个元素被提前。
参数
- it
迭代器到基地位置。
BidirectionalIterator至少应该是一个双向迭代器。 - n
元素位置偏移量(默认为1)。
difference_type是表示BidirectionalIterator类型的迭代器之间的距离的数字类型。
返回值
元素n的迭代器位于it之前。
// prev example #include <iostream> // std::cout #include <iterator> // std::next #include <list> // std::list #include <algorithm> // std::for_each int main () { std::list<int> mylist; for (int i=0; i<10; i++) mylist.push_back (i*10); std::cout << "The last element is " << *std::prev(mylist.end()) << '\n'; return 0; }
复杂度
随机访问迭代器的常量。
对于双向迭代器,n为线性。迭代器有效性
没有效果。
数据范围
该函数访问迭代器,但它永远不会被解引用(调用不会访问指向的对象)。
异常
如果对复制的迭代器执行的任何算术运算抛出,则抛出,提供与此类操作相同的保证级别。
六、next
头文件iterator
template <class ForwardIterator> ForwardIterator next (ForwardIterator it, typename iterator_traits<ForwardIterator>::difference_type n = 1);
获取下一个元素的迭代器
返回一个迭代器,指向如果高级n位置它将指向的元素。它没有被修改。
如果它是随机访问迭代器,则该函数仅使用一次operator +或operator-。 否则,该函数在复制的迭代器上重复使用增加或减少运算符(operator ++或operator–),直到n个元素被提前。
参数
- it
迭代器到基地位置。
ForwardIterator至少应是一个前向迭代器。 - n
元素位置偏移量(默认为1)。
这对随机访问和双向迭代器只是负面的。
difference_type是表示ForwardIterator类型的迭代器之间的距离的数字类型。
返回值
元素n的迭代器远离it。
// next example #include <iostream> // std::cout #include <iterator> // std::next #include <list> // std::list #include <algorithm> // std::for_each int main () { std::list<int> mylist; for (int i=0; i<10; i++) mylist.push_back (i*10); std::cout << "mylist:"; std::for_each (mylist.begin(), std::next(mylist.begin(),5), [](int x) {std::cout << ' ' << x;} ); std::cout << '\n'; return 0; }
复杂度
随机访问迭代器的常量。
否则,线性为n。迭代器有效性
没有效果。
数据范围
该函数访问迭代器,但它永远不会被解引用(调用不会访问指向的对象)。
异常
如果对复制的迭代器执行的任何算术运算抛出,则抛出,提供与此类操作相同的保证级别。
- it
-
Python遍历列表,一次取多个值
2019-12-03 20:39:20Python遍历一个列表,每次取出固定多个元素,直到遍历结束。 其思想跟固定间隔遍历列表一样,只不过是在输出时将源列表切割取值 按固定间隔遍历列表: l1 = [i for i in range(10)] # 遍历列表l1,遍历间隔为3 for i... -
迭代器和生成器
2020-04-25 14:16:50早安,世界,烦恼是每个人不可少的生活小情调,快乐也是,每天睁开眼的那一刻,又便是新的出生,摒弃以流失的种种,珍惜现在每一刻,忘却还未到来的明天,活在当下,不以己悲,以的是生活带来的乐趣和指引。... -
Swift函数式编程十(迭代器和序列)
2021-11-29 15:55:52迭代器(Iterators) 和序列(Sequences) 组成了 Swift 中 for 循环的基础部分。 迭代器 迭代器是每次根据请求生成新元素的“过程”,一个迭代器是遵守一下协议的任何类型: protocol IteratorProtocol { typealias ... -
python生成器和迭代器的区别
2020-12-29 01:29:58匿名用户1级2016-10-13 回答迭代器和生成器都是Python中特有的概念,迭代器可以看作是一个特殊的对象,每次调用该对象时会返回自身的下一个元素,从实现上来看,一个可迭代的对象必须是定义了__iter__()方法的对象,... -
Python中的可迭代对象、迭代器和生成器的异同点
2019-01-16 18:12:01在Python学习之初比较容易混淆可迭代对象、迭代器和生成器。因此,做以总结以辨析其中关键的区别。以下仅为习后个人理解,如有偏差,还请指出! Talk is cheap,show me the picture! 解释之前,我们先来看一张... -
可迭代对象与迭代器对象
2022-03-23 16:06:23可迭代对象与迭代器对象1 > 常见的内置函数21.1 > help() 查看注释信息1.2 > id() 返回一串相当于内存地址的数字1.3 > int() 类型转换、机制转换1.4 > isinstance() 判断数据类型1.5 > pow() 幂... -
C++ STL 迭代器Iterator、五种迭代器类别
2020-08-04 11:43:10针对不同的算法,对迭代器类型的要求也不同,本篇博客我就简单介绍一下C++中的五种迭代器类别。 五种迭代器类别的关系 首先介绍五种迭代器类别: 输入迭代器input iterator 输出迭代器output iterator 前向迭代器... -
python迭代器和生成器
2022-04-19 21:22:34迭代器指的是迭代取值的工具;迭代是一重复的过程;每一次重复都是基于上一次的结果而来;迭代器提供了一种通用的且不依赖于索引的迭代取值方式 -
r 函数返回多个值_【R语言】R语言中的循环
2020-10-22 18:08:22循环,用来处理对多个同类输入做相同事情(即迭代),如对不同列做相同操作、对不同数据集做相同操作。R语言有三种方式实现循环:(1)for循环、while循环(2)apply函数族(3)泛型函数map一. for循环、while循环... -
Python进阶之路 迭代器转换为列表、创建生成器、递归生成器
2019-06-18 20:15:30因此,在讲迭代器转换为列表时,需要给迭代器能够迭代的元素限定一个范围,否则内存就会溢出。要想让迭代器停止迭代,值需要抛出StopIteration异常即可。通过list函数可以直接将迭代器转换为列表。 [例... -
Java中Iterator(迭代器)实现原理
2021-02-25 19:34:47一开始我以为是类似于指针的原理,但是后面的操作让我觉得和指针又差太多,查了资料看了下迭代器的原理,如下:”迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的... -
什么是python的迭代器,迭代器有什么好处
2020-07-12 16:09:441.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个stoplteration异常,以终止迭代(只能往后走,不能往前退) 2.可迭代对象:实现了迭代器协议的对象(如何实现:... -
python迭代器和for循环区别,
2020-12-29 08:50:06对于迭代器来说,__iter__ 返回的是它自身 self,__next__ 则是返回迭代器中的下一个值,最后没有元素时,抛出异常(异常可以被开发者看到)。1.迭代器一定是可迭代对象,因为它实现了__iter__()方法;(推荐学习:... -
详解python三大器——迭代器、生成器、装饰器
2021-10-11 17:04:28聊迭代器前我们要先清楚迭代的概念:通常来讲从一个对象中依次取出数据,这个过程叫做遍历,这个手段称为迭代(重复执行某一段代码块,并将每一次迭代得到的结果作为下一次迭代的初始值)。 可迭代对象(iterable):... -
C++菜鸟学习笔记系列(9)——迭代器
2018-10-02 11:44:15本期主题:迭代器介绍 我们在C++菜鸟学习笔记系列(7)、C++菜鸟学习笔记系列(8)中分别介绍了C++语言标准库类型string,vector 的定义及使用。 对于string类型的对象我们可以通过范围for语句和索引的方式访问... -
五、迭代器--迭代器类型详述
2017-08-16 15:47:13五、迭代器标签(空格分隔): c++STL1. 迭代器及其特性 迭代器本身就是一种对象 迭代器不是通用指针,而是指向数组...输入:为程序需要数据源提供接口,数据源可以是容器,数据流等,输入迭代器只能从一个序列读入数据 -
java迭代器退出迭代_使用Java迭代器修改数据时要小心
2020-07-10 05:35:52随着本学期的结束,我想我会分享一个关于如何非常熟悉Java迭代器的小故事。 现实世界语境 就上下文而言,我开设了第二年软件组件课程,这是尝试进入该专业的学生的最后障碍。 当然,这门课程对学生来说压力很大,... -
C++中STL为什么要使用迭代器?
2018-09-20 00:26:45原因: 1、通过迭代器访问容器,可以避免许多错误,同时...3、迭代器本身有很多优点,可以弥补C++语言的不足,比如它的iterator_category,可以得到迭代器所指向的类别,这样可以根据不同的类别的特性,提供不同的... -
c++迭代器(iterator)详解
2019-02-14 16:03:361. 迭代器(iterator)是一中检查容器内元素并遍历元素的数据类型。 (1) 每种容器类型都定义了自己的迭代器类型,如vector: vector&...(2) 使用迭代器读取vector中的每一个元素: vector<in... -
Python中的内建函数,可迭代对象,迭代器
2019-04-10 19:55:17Python中的内建函数和可迭代对象,迭代器 求值标识 id() #标识id 返回对象的唯一标识,CPython返回内存地址 hash() #哈希, 返回对象的哈希值 len(s) -->返回一个集合类型的元素个数 range(start,stop[,... -
多次读取reduce函数中迭代器的数据
2016-05-13 16:30:20spark,hadoop交流群,QQ群号:521066396,欢迎加入共同学习,一起进步~第一次碰到读取reduce函数中迭代器的数据只能取一次的问题。为了优化,在reduce函数中,Iterable values只能被读取一次。查阅相关资料,如果要... -
迭代器、可迭代对象、生成器
2018-01-03 19:37:35假如我们自己写了一个数据类型,希望这个数据类型里的东西也可以使用for被一个一个的取出来,那我们就必须满足for的要求。这个要求就叫做“协议”。 可以被迭代要满足的要求就叫做可迭代协议。*可迭代协议的定义... -
关于python的可迭代对象、迭代器、生成器的理解
2021-02-03 05:28:07最近有朋友问到python中的迭代器和生成器的区别和作用,以及如何定义和区分,今天在这里稍微总结一下。可迭代对象定义:可迭代对象必须实现 "_iter_()" 方法。python中的字符串、列表、元组、字典、集合、文件对象等... -
python基础(十六):迭代器、生成器
2020-05-08 21:53:15迭代器即用来迭代取值的工具,而迭代是重复反馈过程的活动,其目的通常是为了逼近所需的目标或结果,每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值,单纯的重复并不是迭代 ... -
JS中的迭代器和生成器
2017-06-02 17:32:00迭代器iterator是一个object,这个object有一个next函数,该函数返回一个有value和done属性的object,其中value指向迭代序列中的下个值。这样看来迭代器定义简直简单的感人T_T. 例如下列code function ... -
JAVA设计模式--迭代器模式
2017-02-11 13:01:59目录 一、什么是迭代器模式 ...提供一种方法顺序访问一个聚合(指一组对象的组合结构,如:Java中的集合、数组等)对象中各个元素,而又不需暴露该对象的内部表示。 迭代器模式的本质:控制访问...