Python内置类型(5)--迭代器类型
指能够被内置函数
next
调用并不断返回下一个值,直到最后抛出StopIteration
错误表示无法继续返回下一个值的对象称为迭代器(Iterator
)
其实以上的说法只是侠义上的迭代器的定义,在python中,迭代器还需要实现可迭代接口(Iterable
),可迭代接口需要返回的是一个迭代器对象,这样迭代器就能够被for
语句进行迭代。
迭代器对象初步认知
在python
中,没有内置迭代器类型的对象,但是可以通过内置函数iter
将str
、tuple
、list
、dict
、set
等类型转换成一个迭代器对象。
>>> 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
。
Iterator
和Iterable
的关系
在模块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
总结
- 凡是可作用于
for
语句循环的对象都是Iterable
可迭代类型。 - 凡是可作用于
next()
函数的对象都是Iterator
迭代器类型。 str
、tuple
、list
、dict
、set
等类型是Iterable
可迭代类型,但不是Iterator
迭代器;通过Iterable
可迭代类型的__iter()__
方法可以获得一个Iterator
迭代器对象,从而使得它们可以被for语句循环。Python
的for
循环本质上就是通过调用Iterable
可迭代对象的__iter()__
方法获得一个Iterator
迭代器对象,然后不断调用Iterator
迭代器对象__next()__
方法实现的。
Python内置类型(5)--迭代器类型的更多相关文章
- Python内置类型性能分析
Python内置类型性能分析 timeit模块 timeit模块可以用来测试一小段Python代码的执行速度. class timeit.Timer(stmt='pass', setup='pass' ...
- 为什么继承 Python 内置类型会出问题?!
本文出自"Python为什么"系列,请查看全部文章 不久前,Python猫 给大家推荐了一本书<流畅的Python>(点击可跳转阅读),那篇文章有比较多的"溢 ...
- Python 内置类型 dict, list,线程安全吗
近段时间发现一个 Python 连接数据库的连接是线程不安全的,结果惹得我哪哪儿都怀疑变量的多线程是否安全的问题,今天终于找到了正确答案,那就是 Python 内置类型 dict,list ,tupl ...
- Python——内置类型
Python定义了丰富的数据类型,包括: 数值型:int, float, complex 序列:(iterable) str, unicode, tuple, list, bytearray, buf ...
- 易被忽略的Python内置类型
Python中的内置类型是我们开发中最常见的,很多人都能熟练的使用它们. 然而有一些内置类型确实不那么常见的,或者说往往会被我们忽略,所以这次的主题就是带领大家重新认识这些"不同寻常&quo ...
- python内置类型详细解释
文章编写借鉴于内置类型 - Python 3.7.3 文档,主要用于自己学习和记录 python主要内置类型包括数字.序列.映射.类.实例和异常 有些多项集类是可变的.它们用于添加.移除或重排其成员的 ...
- Python内置类型(6)——生成器
上节内容说到Python的for语句循环本质上就是通过调用Iterable可迭代对象的__iter()__方法获得一个Iterator迭代器对象,然后不断调用Iterator迭代器对象__next() ...
- Python内置类型——set
Python中,内置类型set和frozenset用来表示集合,我们首先查看这两个类型支持的特殊对象,从而可以理解他们的特性. >>> dir(set) ['__and__', '_ ...
- 4、python内置类型(0529)
支持运算:索引,切片,min(), max(), len()等 支持操作:对象的自有的方法 对字符串操作的内置方法获取:str. //敲tab键补全 获取某个内建命令的属性和方法列表:dir( ...
随机推荐
- linux resin 安装 配置 相关
resin跟tomcat一样,也是解析jsp网站的,也需要JDK的支持,所以第一步也是安装JDK,安装JDK的方法参考Tomcat中的安装JDK部分.下面介绍安装resin.resin官网http:/ ...
- ABP 权限拦截 第二篇
由于访问人数过多,我今天从新整理一下ABP权限认证机制,帮助大家更容易读懂 1.Abp 的权限拦截主要通过过滤器, public class AbpAuthorizationFilter : I ...
- 2019.02.19 bzoj2655: calc(生成函数+拉格朗日插值)
传送门 题意简述:问有多少数列满足如下条件: 所有数在[1,A][1,A][1,A]之间. 没有相同的数 数列长度为nnn 一个数列的贡献是所有数之积,问所有满足条件的数列的贡献之和. A≤1e9,n ...
- Log4J日志整合及配置详解
Log4j有三个主要的组件:Loggers(记录器),Appenders (输出源)和Layouts(布局).这里可简单理解为日志类别,日志要输出的地方和日志以何种形式输出.综合使用这三个组件可以轻松 ...
- ABP框架系列之十九:(Debugging-调试)
While it's not generally needed, you may want to step into ABP's source code while you debugging you ...
- Spring通过在META-INF/spring.handlers中的属性进行配置文件解析
在Spring的入口函数refresh()之中进行的. AbstractApplicationContext ConfigurableListableBeanFactory beanFactory = ...
- 4k项目--PHY通道绑定的两种模式
1.通道绑定有两种模式: • PMA bonding• PMA and PCS bonding GT通道是不支持通道绑定的 2.PMA绑定 PMA绑定减少了PMA之间的通道之间的Skew.并且在PMA ...
- ASP.NET对大文件上传的解决方案
在ASP.NET 开发的过程中,最大的问题就在于上传大文件时让开发者尤为的头疼,而且,上传时无法方便的做到多线程的操控和上传进度的显示.笔者在此给大家推荐一款简单易用的上传组件,从而快速便捷得解决了 ...
- ssm中通过ajax或jquer的validate验证原密码与修改密码的正确性
一.ajax 1. <script type="text/javascript"> //验证原密码1.ajax,正则 var ok1=false,ok2=false,o ...
- DL_1_week1_概论
standard NN,CNN,RNN,custom hybrid NN architecture(Radar) 结构化数据是数据的数据库,相比结构化数据计算机更难理解非结构化数据,人生来很容易理解非 ...