迭代器 / Iteratior


目录

  1. 可迭代对象与迭代器协议
  2. 迭代器
  3. 迭代器(模拟)的建立

1 可迭代对象与迭代器协议


对于迭代器首先需要了解两个定义,迭代器协议 (Iterator Protocol) 与可迭代对象 (Iterable) ,

迭代器协议 Iterator Protocol:

迭代器协议是指对象能够提供 next() 方法 (__next__()) ,返回迭代中的下一项,或者引起一个 StopIteration 异常,以终止迭代。

可迭代对象 Iterable:

可迭代对象则是指,实现了迭代器协议的对象,例如 list、tuple、dict 等,这些都属于可迭代对象 (Iterable),但是却不是迭代器对象 (Iterator)。但可以使用内建函数 iter(),利用可迭代对象生成一个迭代器对象。

2 迭代器


对于迭代器来说,需要的是一个 __next__() 特殊函数,也就是迭代器与可迭代对象的一个重要差别。通过示例可以看到,可迭代对象是不具有 __next__() 方法的,而迭代器则有。

 lis = [1, 2]
print(hasattr(lis, '__iter__')) # True
print(hasattr(lis, '__next__')) # False
lix = iter(lis)
print(hasattr(lix, '__iter__')) # True
print(hasattr(lix, '__next__')) # True

Note:

1. 内置函数 iter() 会调用对象的 __iter__() 方法,因此,可迭代对象具有 __iter__() 方法;

2. 内置函数 next() 会调用对象的 __next__() 方法,因此迭代器则需要具有 __next__() 方法;

3. 当 for 循环处理可迭代对象时,其本质是先调用了可迭代对象的 __iter__() 方法,使其变成迭代器后,再进行 next() 循环迭代

利用 help 函数分别查看两个对象,

 from collections import Iterator, Iterable
help(Iterator)
help(Iterable)

通过对迭代器的查看结果可以发现,Iterator 是以 Iterable 作为基类的,且多了一个 __next__() 方法。

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__'}) 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__'})

3 迭代器(模拟)的建立


对于一个迭代器的建立,主要是利用 iter() 函数调用可迭代对象内部的 __iter__() 函数返回一个迭代器对象。而此处将建立一个自己的类,来模拟迭代器的一些行为特征。建立的方式可分为两种,一种是直接建立 Iterator,另一种是继承 Iterable。

直接建立 Iterator

直接建立一个类 MyIterator,并完成迭代器必须的特殊方法 __next__ 的定义,同时加入了对 __iter__ 函数的定义,以便在for循环的时候返回实例本身(已具备 __next__ 方法因此只需返回实例即可,后面会介绍模拟可迭代对象的 for 循环迭代器生成)。定义的 __next__ 方法模拟了 range() 的行为。

 class MyIterator():
def __init__(self, imin, imax):
self.count = imin - 1
self.limit = imax def __iter__(self):
return self def __next__(self):
self.count += 1
if self.count >= self.limit:
raise StopIteration
return self.count it = MyIterator(0, 7)
for i in range(7):
print(next(it))
# Output: 0 1 2 3 4 5 6 for i in MyIterator(0, 7):
print(i)
# Output: 0 1 2 3 4 5 6

利用 next() 和 for 循环两种方式遍历迭代器,可以看到输出正常。

继承 Iterable

第二种方式需要建立一个自己的可迭代对象,并模拟可迭代对象的行为。定义一个可迭代对象类 MyIterable,对可迭代对象不定义其 __next__ 方法,只定义 __iter__ 方法供 iter() 函数调用,在 __iter__ 方法中,将会利用一个 MyIterable 的子类 geneIterator (模拟 Iterator 基于 Iterable )来生成可迭代对象的子类迭代器。

 class MyIterable():
def __init__(self, imin, imax):
self.imin = imin
self.imax = imax
self.count = imin - 1
self.limit = imax #def __iter__(self):
# return self def __iter__(self):
return GeneIterator(self)

这里定义了一个 MyIterable 的子类,GeneIterator 继承自 MyIterable,初始化时接收一个 Iterable 类实例作为参数,并且重载了一个 __next__() 函数用于实现迭代器的特性。

 class GeneIterator(MyIterable):
def __init__(self, iterable):
  # This __init__ function pass two value to the instance of geneIterator
MyIterable.__init__(self, iterable.imin, iterable.imax) def __next__(self):
self.count += 1
if self.count >= self.limit:
raise StopIteration
return self.count

Note:

此处最值得注意的是,GeneIterator(self) 中的 self MyIterable 的实例,作为初始化时传入参数iterable而存在,而 MyIterable.__init__(self, iterable.imin, iterable.imax) 中的 self 则是 GeneIterator 的实例,此处传入父类的初始化函数中的目的在于,让 self 通过 MyIterable 的初始化获得(继承) count limit 参数。

最后验证迭代器

 for i in MyIterable(0, 7):
print(i)
# Output: 0 1 2 3 4 5 6

通过上面两个类的继承关系,此处的 for 循环会先调用 MyIterable 的 __iter__ 方法,获得一个具有 __next__ 方法的 GeneIterator 实例,最终使用 next() 方法进行迭代。

Python的程序结构[6] -> 迭代器/Iterator -> 迭代器浅析的更多相关文章

  1. Python的程序结构[7] -> 生成器/Generator -> 生成器浅析

    生成器 / Generator 目录 关于生成器 生成器与迭代器 生成器的建立 通过迭代生成器获取值 生成器的 close 方法 生成器的 send 方法 生成器的 throw 方法 空生成器的检测方 ...

  2. Python基本程序结构

    条件判断: 计算机之所以能做很多自动化的任务,因为它可以自己做条件判断.比如,输入用户年龄,根据年龄打印不同的内容,在Python程序中,用if语句实现:

  3. Python的程序结构[5] -> 模块/Module[0] -> 内建模块 builtins

    builtins 内建模块 / builtins Module 在Python的模块中,有一种特殊模块,无需导入便可以使用,其中包含了许多内建函数与类. builtins 模块内容 / builtin ...

  4. Python的程序结构[0] -> 属性/Property[0] -> 类属性、实例属性和私有属性

    类属性.实例属性和私有属性 Python中类的属性主要包括类属性,实例属性和私有属性,下面是对三种属性的简单介绍 类属性 / Class Property 类属性在__init__()之外初始化,在外 ...

  5. Python的程序结构[1] -> 方法/Method[0] -> 类实例方法、私有方法和抽象方法

    类实例方法.私有方法和抽象方法 Python中最常用的就是类实例方法,类似于属性中的类实例属性,同时,也存在与私有属性类似方法,即私有方法,下面介绍这两种常见的方法,以及一种特殊意义的类实例方法 -- ...

  6. Python的程序结构[1] -> 方法/Method[1] -> 静态方法、类方法和属性方法

    静态方法.类方法和属性方法 在 Python 中有三种常用的方法装饰器,可以使普通的类实例方法变成带有特殊功能的方法,分别是静态方法.类方法和属性方法. 静态方法 / Static Method 在 ...

  7. Python的程序结构[1] -> 方法/Method[2] -> 魔术方法 __init__ / __del__ / __new__

    魔术方法 / Magic Method 魔法方法就是可以给你的类增加魔力的特殊方法(实质应称为特殊方法,魔术方法在JavaScript中有所体现,对象具有不透明特性,而且无法在自定义对象中模拟这些行为 ...

  8. Python的程序结构[2] -> 类/Class[0] -> 类的特殊属性

    类的特殊属性 / Special Property of Class Python 中通过 class 进行类的定义,类可以实例化成实例并利用实例对方法进行调用. 类中还包含的一些共有的特殊属性. 特 ...

  9. Python的程序结构[2] -> 类/Class[1] -> 基类与继承

    基类与继承 / Base Class and Inheritance Class 面向对象的特性使得 Python 中不可避免地需要使用到类和类的继承,类的继承可以使得代码很好的被重用.下面以一些代码 ...

随机推荐

  1. 超链接标签的CSS伪类link,visited,hover,active

    CSS伪类,是一种特殊的类,它针对到CSS选择器起作用,使选中的标签或元素产生特定的效果. CSS伪类的语法就是: 选择器 : 伪类名 { 属性 : 属性值 } 用的最多的伪类就是超链接a的伪类,有: ...

  2. js对数组去重的完整版

    数组去重是很常见的一个需求,而各种各样的姿势也很多,常见的如indexOf,或者hash,但是他们还是有缺陷,这里我查了一些资料做补充. 一般方式 //一般方法->使用indexOf Array ...

  3. linux部署环境配置

    https://blog.csdn.net/dsczxcc/article/details/78728330

  4. linux shell 总结 (整理)

    ls /usr/bin/ info #路径操作 dirname basename #“”和‘’与 ` ` 在shell变量中的区别 “ ” 允许通过$符引用其他变量 ‘’禁止引用其他变量符,视为普通字 ...

  5. Metadata 的概念

    https://www.ibm.com/developerworks/cn/cloud/library/1509_liukg_openstackmeta/ http://mathslinux.org/ ...

  6. 深入理解css之absolute

    在慕课网上看到的张鑫旭大神的视频,做的笔记,以便日后翻看. 绝对定位与float 1.绝对定位和float有一样的特性,都有包裹性,和破坏性. 2.absolute和relative 如果不把他们俩放 ...

  7. [转]Shell dev-null详解

    转自: https://blog.csdn.net/wenwenxiong/article/details/46882733 1,可以将/dev/null看作"黑洞". 它非常等价 ...

  8. 使用java实现对称加密解密(AES),非对称加密解密(RSA)

    对称加密:双方采用同样的秘钥进行加密和解密.特点是速度快,但是安全性没有非对称加密高 非对称加密:接收方生成的公有秘钥公布给发送方,发送方使用该公有秘钥加密之后,发送给接收方,然后接收方使用私有秘钥解 ...

  9. HttpRuntime.Cache再学习

    摘抄: 可以看到:读缓存,其实是在调用Get方法,而写缓存则是在调用Insert方法的最简单的那个重载版本. 注意了:Add方法也可以将一个对象放入缓存,这个方法有7个参数,而Insert也有一个签名 ...

  10. poj 1035 纯正的字符串水

    Spell checker Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 22673   Accepted: 8258 De ...