指能够被内置函数next调用并不断返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值的对象称为迭代器(Iterator)

其实以上的说法只是侠义上的迭代器的定义,在python中,迭代器还需要实现可迭代接口(Iterable),可迭代接口需要返回的是一个迭代器对象,这样迭代器就能够被for语句进行迭代。

迭代器对象初步认知

python中,没有内置迭代器类型的对象,但是可以通过内置函数iterstrtuplelistdictset等类型转换成一个迭代器对象。

>>> s = 'abc'
>>> next(s)
Traceback (most recent call last):
File "<pyshell#27>", line 1, in <module>
next(s)
TypeError: 'str' object is not an iterator
# 以上报错信息可以看出`str`不是迭代器
>>> it_s = iter(s)
>>> next(it_s)
'a'
>>> next(it_s)
'b'
>>> next(it_s)
'c'
>>> next(it_s)
Traceback (most recent call last):
File "<pyshell#31>", line 1, in <module>
next(it_s)
StopIteration
# 以上报错信息可以看出`iter(str)`是迭代器

通过不断的调用next(iterator)方法来获取下一个值,这样其实不怎么方便,python提供了更为简洁的方法,即for循环。for循环每执行一次即相当于调用了一次next(iterator)方法,直到捕获到StopIteration异常退出循环。

>>> it_s = iter(s)
>>> for c in it_s:
print(c) a
b
c # 以上的例子是使用for循环遍历迭代器

模块collections中的类型Iterator就是迭代器的抽象基类,所有的迭代器都是Iterator的实例。即如果一个对象是Iterator的实例,则说明此对象是迭代器。

from collections import Iterator

>>> isinstance(s,Iterator)
False >>> isinstance(it_s,Iterator)
True # 以上信息证实了`str`不是迭代器,而`iter(str)`是迭代器

如何自己实现一个迭代器

根据python鸭子类型的特性,我们自定义的类型中,只要实现了__next()__方法,该方法在每次被调用时不断返回下一个值,直到无法继续返回下一个值时抛出StopIteration异常即可(next(iterator)实际上调用的是iterator内部的__next()__方法)。

定义自己的迭代器

>>> class MyIter():

    def __init__(self,max_value):
self.current_value = 0
self.max_value = max_value def __next__(self):
if self.current_value < self.max_value:
result = self.current_value
self.current_value += 1
return result
else:
raise StopIteration

验证next方法是否不停返回下一个值

>>> my_iter = MyIter(3)
>>> next(my_iter)
0
>>> next(my_iter)
1
>>> next(my_iter)
2
>>> next(my_iter)
Traceback (most recent call last):
File "<pyshell#31>", line 1, in <module>
next(my_iter)
StopIteration

验证对象是否可以用于for循环

>>> my_iter = MyIter(3)
>>> for i in my_iter:
print(i) Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
for i in my_iter:
TypeError: 'MyIter' object is not iterable

验证对象是否是Iterator实例

>>> from collections import Iterator
>>> isinstance(my_iter,Iterator)
False

从上面的验证可以看出仅仅实现__next()__方法的对象还不是迭代器,真正的迭代器还需要实现一个可迭代接口Iterable

IteratorIterable的关系

在模块collections中的类型Iterator就是迭代器的抽象基类,其实它里面还定义了类型Iterable,它是可迭代对象的抽象基类。先分别通过help命令查看他们的定义:

>>> from collections import Iterator, Iterable
>>> help(Iterator)
Help on class Iterator in module collections.abc: class Iterator(Iterable)
| Method resolution order:
| Iterator
| Iterable
| builtins.object
|
| Methods defined here:
|
| __iter__(self)
|
| __next__(self)
| Return the next item from the iterator. When exhausted, raise StopIteration
|
| ----------------------------------------------------------------------
| Class methods defined here:
|
| __subclasshook__(C) from abc.ABCMeta
| Abstract classes can override this to customize issubclass().
|
| This is invoked early on by abc.ABCMeta.__subclasscheck__().
| It should return True, False or NotImplemented. If it returns
| NotImplemented, the normal algorithm is used. Otherwise, it
| overrides the normal algorithm (and the outcome is cached).
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| __abstractmethods__ = frozenset({'__next__'}) >>> help(Iterable)
Help on class Iterable in module collections.abc: class Iterable(builtins.object)
| Methods defined here:
|
| __iter__(self)
|
| ----------------------------------------------------------------------
| Class methods defined here:
|
| __subclasshook__(C) from abc.ABCMeta
| Abstract classes can override this to customize issubclass().
|
| This is invoked early on by abc.ABCMeta.__subclasscheck__().
| It should return True, False or NotImplemented. If it returns
| NotImplemented, the normal algorithm is used. Otherwise, it
| overrides the normal algorithm (and the outcome is cached).
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| __abstractmethods__ = frozenset({'__iter__'})

通过上面的代码,可以清楚的看出迭代器类型Iterator继承自可迭代类型Iterable,可迭代Iterable继承自object基类,迭代器Iterator类型包含__iter()____next()__方法,而可迭代类型Iteratble仅仅包含__iter__()。可迭代对象,通过__iter()__返回一个迭代器对象,迭代器对象的__next()__方法则实际用于被循环。

完善自己实现一个迭代器

我们现在再将MyIter类型实现可迭代接口Iterable,即实现__iter__()方法。

>>> class MyIter():

def __init__(self,max_value):
self.current_value = 0
self.max_value = max_value def __iter__(self):
return self def __next__(self):
if self.current_value < self.max_value:
result = self.current_value
self.current_value += 1
return result
else:
raise StopIteration

验证对象是否可以用于for循环

>>> my_iter = MyIter(3)
>>> for i in my_iter:
print(i) 0
1
2

验证对象是否是Iterator实例

>>> from collections import Iterator
>>> isinstance(my_iter,Iterator)
True

总结

  1. 凡是可作用于for语句循环的对象都是Iterable可迭代类型。
  2. 凡是可作用于next()函数的对象都是Iterator迭代器类型。
  3. strtuplelistdictset等类型是Iterable可迭代类型,但不是Iterator迭代器;通过Iterable可迭代类型的__iter()__方法可以获得一个Iterator迭代器对象,从而使得它们可以被for语句循环。
  4. Pythonfor循环本质上就是通过调用Iterable可迭代对象的__iter()__方法获得一个Iterator迭代器对象,然后不断调用Iterator迭代器对象__next()__方法实现的。

Python内置类型(5)--迭代器类型的更多相关文章

  1. Python内置类型性能分析

    Python内置类型性能分析 timeit模块 timeit模块可以用来测试一小段Python代码的执行速度. class timeit.Timer(stmt='pass', setup='pass' ...

  2. 为什么继承 Python 内置类型会出问题?!

    本文出自"Python为什么"系列,请查看全部文章 不久前,Python猫 给大家推荐了一本书<流畅的Python>(点击可跳转阅读),那篇文章有比较多的"溢 ...

  3. Python 内置类型 dict, list,线程安全吗

    近段时间发现一个 Python 连接数据库的连接是线程不安全的,结果惹得我哪哪儿都怀疑变量的多线程是否安全的问题,今天终于找到了正确答案,那就是 Python 内置类型 dict,list ,tupl ...

  4. Python——内置类型

    Python定义了丰富的数据类型,包括: 数值型:int, float, complex 序列:(iterable) str, unicode, tuple, list, bytearray, buf ...

  5. 易被忽略的Python内置类型

    Python中的内置类型是我们开发中最常见的,很多人都能熟练的使用它们. 然而有一些内置类型确实不那么常见的,或者说往往会被我们忽略,所以这次的主题就是带领大家重新认识这些"不同寻常&quo ...

  6. python内置类型详细解释

    文章编写借鉴于内置类型 - Python 3.7.3 文档,主要用于自己学习和记录 python主要内置类型包括数字.序列.映射.类.实例和异常 有些多项集类是可变的.它们用于添加.移除或重排其成员的 ...

  7. Python内置类型(6)——生成器

    上节内容说到Python的for语句循环本质上就是通过调用Iterable可迭代对象的__iter()__方法获得一个Iterator迭代器对象,然后不断调用Iterator迭代器对象__next() ...

  8. Python内置类型——set

    Python中,内置类型set和frozenset用来表示集合,我们首先查看这两个类型支持的特殊对象,从而可以理解他们的特性. >>> dir(set) ['__and__', '_ ...

  9. 4、python内置类型(0529)

    支持运算:索引,切片,min(), max(), len()等 支持操作:对象的自有的方法 对字符串操作的内置方法获取:str.     //敲tab键补全 获取某个内建命令的属性和方法列表:dir( ...

随机推荐

  1. iOS之Safari调试webView/H5页面

    之前做过混合开发,用的是JavaScriptCore+OC+UIWebView. Safari调试功能真的很有用,通过它可以轻松定位问题的所在,下面说说怎么调试. 开启Safari开发菜单 在Mac的 ...

  2. URL重写中的中文参数问题

    在做搜索功能时,需要输入关键字,如果搜索出来的结果很多,又需要分页.这里用URL重写技术(即href="?keyword=关键字&page=分页数"),就涉及到了传递中文关 ...

  3. Android开发中同时存在多个ListView的处理

    在Android开发过程中,有的时候我们需要在一个页面中通过多个ListView展示不同的数据,让用户直观上感觉是一个ListView在变换着数据. 假设有两个ListView,listView1和L ...

  4. 如何建一个maven项目

    使用Maven创建web项目 1.打开Eclipse, 选择File -> New -> Other,在New窗口中选择 Maven -> Maven Project:点击Next. ...

  5. 探索未知种族之osg类生物---呼吸分解之渲染遍历一

    总结 前面我们基本上已经完成对ViewerBase::frame()函数的探究,只剩下renderingTraversals()渲染遍历的探究,虽然就剩下了一个函数,但是这却是最重要的,不可少的一个步 ...

  6. python 数据可视化(matplotlib)

    matpotlib 官网 :https://matplotlib.org/index.html matplotlib 可视化示例:https://matplotlib.org/gallery/inde ...

  7. Hadoop 系列(三)Java API

    Hadoop 系列(三)Java API <dependency> <groupId>org.apache.hadoop</groupId> <artifac ...

  8. Python之路(第二十九篇) 面向对象进阶:内置方法补充、异常处理

    一.__new__方法 __init__()是初始化方法,__new__()方法是构造方法,创建一个新的对象 实例化对象的时候,调用__init__()初始化之前,先调用了__new__()方法 __ ...

  9. ScrollView嵌套Linearlayout显示不全的解决办法

    以为ScrollView只能嵌套一个元素,所以把几个控件都包裹在了一个LinearLayout中了.但是发现底部显示不全,滑动不到最底下. 代码: <ScrollView android:id= ...

  10. tensorflow o. 到 tensorflow 1. 部分改变

    一下内容为笔者实际应用中遇到的问题,可能(必须)不全,后面会持续更新. (1) tf.nn.run_cell   改为   tf.contrib.rnn (2) tf.reduce_mean   改为 ...