迭代器

 

 

迭代就是快速地在原来的版本上添加新功能。

迭代器是Python中一种特殊的对象。

迭代就是在原来的基础上,得到一个新的东西。

 

 

一个对象是可迭代的  <==>   能放到 for x in 后面   <==>  instance(对象, Iterable)为True   <==>  有__iter__()方法

迭代器对象     <==>  isinstance(xxx, Iterator)    <==>   实现了__iter__() 和__next__()方法

 

 

 

 

一、可迭代对象

1. 什么是可迭代的对象?

一个对象是可迭代的  <==>   能放到 for x in 后面   <==>  instance(对象, Iterable)为True   <==>  有__iter__()方法

 

能够放在for x in 后面的,就是可迭代的(iterable),比如字符串、列表、元组、字典、集合。但是数字类型就不行,比如:

 

例1:

结果:

 

 

2. 怎么判断一个对象是可迭代的?

我怎么知道一个对象是否可以迭代呢?

只要判断是Iterable的实例对象就可以了。【例2】

 

例2:

 

结果:

 

前两个可以迭代。12不能迭代。

 

 

3. 如果我创建了一个类,怎么让这个类是可迭代的呢?

如果想要一个对象称为一个可迭代的对象(即可以使用for循环),那么必须实现__iter__()方法。【例3】【例4】

 

 

例4:

 

 

 

实现了__iter__方法,就是可迭代对象了,就能够放到for后面了。

但是还是报错了,说iter()方法返回的不是一个迭代器对象。

 

 

那什么是迭代器对象呢?为什么iter()方法返回呢?

我们需要知道什么是迭代器,以及for循环的原理。

 

 

 

二、迭代器

迭代器对象 <==>  实现了__iter__() 和__next__()方法   <==>  isinstance(xxx, Iterator)

 

 

结果:

 

三、for循环执行原理

for temp in xxx_obj:

     pass

 

 

 

 

步骤1. 判断xxx_obj是否是可迭代。如果不可迭代会报错。【例1】 

步骤2. 如果是可迭代的,for循环会自动调用iter()函数,并传入xxx_obj对象。iter()函数,会自动xxx_obj对象的__iter__()方法,得到返回值。【例2】【例3】【例4】

步骤3. iter()函数的返回值要求是一 报错。【例2】【例3】

步骤4. 返回了迭代器iterator之后,for每次循环就调用一次next(iterator)函数。next(iterator)函数会自动调用迭代器iterator的__next__()方法,得到一个结果。【例5】

           迭代器中的__next__返回的是什么,temp就是什么。。每for一次,就会调用一次next,next返回什么就用什么。。【例6】

 

 

for循环传入的参数是xxx_obj,xxx_obj返回的是一个迭代器。迭代器的__next__()方法给for循环什么,for循环就用什么。

 

 

 

例1:如果不是可迭代对象,则会报错。

 

结果:

 

例2:验证:iter()函数会自动调用对象的__iter__()方法。并且如果返回值不是迭代器会报错。

 

结果:

 

例3:iter()返回的是一个迭代器对象,就不报错了。

 

结果:

 

 

例4:验证for循环会自动调用__iter__()方法。

 

结果:


 

说明了,for循环会调用iter()方法。

 

 

例5:next(迭代器)方法会自动调用迭代器的__next__方法。

 

结果:

 

 

例6:每for一次就是返回一次迭代器的结果。

 

结果:

 

共执行了5次for循环。迭代器返回了五次"aaa"。

 

 

 

四、自己实现一个类,能够使用for循环遍历其中的值

现在我们已经知道了for循环的原理。我们接着上面的例6完成后面的部分,完成for循环能够遍历到Classmate类的列表的内容。

 

现在迭代器中的__next__方法能够返回"aaa"了。但是我们想返回的是classmate对象的列表。所以只要把classmate传给__next__方法。就行了。

 

【改进一】

 

结果:

可以输出小王了。

 

 

【改进二】增加遍历的代码

 

结果:

 

【改进三】怎么结束遍历呢?

for循环并不知道一共有几个,当遍历完了,取到的是None。

 

结果:

 

当取完之后,抛出一个异常。当for循环得到异常之后,就停了。

 

 

到此为止,for循环就实现了~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

【继续改进:终版】

我们看到,是实现了__iter__()方法就是可迭代对象,可迭代对象返回 了迭代器对象。而迭代器对象实现了__iter__() 和__next__()方法,__next__方法又返回了可迭代对象的内容。

那我直接在可迭代对象中,加上__next__方法,就可以即是可迭代对象,又是迭代器了。这样就可以少写一个类了。

 

 

结果:

 

执行过程是这样的:

步骤1. 判断classmate是否是可迭代对象。因为Classmate类有__iter__方法,所以是可迭代对象。

步骤2. 如果是可迭代的,for循环会自动调用iter()函数,并传入classmate对象。iter(classmate)函数,会自动classmate对象的__iter__()方法,得到返回值。

步骤3. iter(classmate)函数的返回值要求是self。因为classmate有__iter__方法和__next__()方法,所以是一个迭代器。

步骤4. 返回了迭代器classmate之后,for每次循环就调用一次next(classmate)函数。next(classmate)函数会自动调用迭代器classmate的__next__()方法,得到一个结果。

           每for一次,就会调用一次next,next返回什么就用什么。。

 

 

五、迭代器的应用

 

5.1 字符串、列表、元组、字典、集合不是迭代器,是可迭代对象。

 

 

结果:

 

 

5. 2 zip、enumerate 等itertools里的函数是迭代器

 

例1:

 

例2:

 

结果:

 

 

5. 3 文件是一个迭代器

 

结果:

 

5.4 range()不是迭代器

 

 

 

range()函数很特别,不是迭代器。具有序列的性质。【例1】

迭代器可以被耗尽,而range()不会。【例2】【例3】

 

range()不是迭代器,也不是一个序列。但是又有迭代器和序列的性质。那range()是个什么东西呢?

我们称range()是一个懒序列。range()是一个序列类型。但里面又不包括任何内容,并不是显示存储的。它是通过计算来回答的。

 

 

例1:

 

结果:

 

例2:迭代器可以耗尽

 

结果:

 

 

 

例3:

 

结果:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值