Python 拓展之迭代器
写在之前
今天来讲讲「迭代器」的内容,其实已经拖了好多天了,感觉再不写就要忘记了。「迭代」相信对你来说已经不陌生了,我前面曾经专门用一篇文章来讲,如果你已经没有什么印象的话,就再点进去看看(零基础学习 Python 之初识迭代)。
迭代器
首先我们先来看一种检查是否可迭代的方法:
>>> hasattr(list,'__iter__')
True
可以用上面的这种方法检查已经学习过的其他默认类型的对象,比如字符串,列表,字典等是否是可迭代的。
iter() 是一个特殊方法,它是迭代规则的基础,有了它,就说明对象是可迭代的。跟迭代有关的一个内建函数 iter(),这个函数我们在之前的文章中介绍过,它返回的是一个迭代器对象,比如像下面这样:
>>> list1 = [1,2,3,4]
>>> iter_list = iter(list1)
>>> iter_list
<list_iterator object at 0x00000000021CE438>
从上述代码的结果可以看出,iter_list 引用的是迭代器对象。那么在这里有一个问题,iter_list 和 list1 有区别吗?我们来试一下:
>>> hasattr(list1,'__iter__')
True
>>> hasattr(iter_list,'__iter__')
True
从上面看出它们都有 iter,说明它们都是可迭代的。
>>> hasattr(list1,"__next__")
False
>>> hasattr(iter_list,"__next__")
True
我们把像 iter_list 所引用的对象那样,称之为「迭代器对象」。显而易见的是,迭代器对象必然是可迭代的,反正则不一定。且 Python 中迭代器对象实现的是 next() 方法。
为了体现一下 Python 在这的强大之处,我们先来写一个迭代器对象:
class MyRange:
   def __init__(self,n):
       self.i = 1
       self.n = n
   def __iter__(self):
       return self
   def __next__(self):
       if self.i <= self.n:
           i = self.i
           self.i += 1
           return i
       else:
           raise StopIteration()
if __name__ == "__main__":
   x = MyRange(5)
   print([i for i in x])
上述代码的运行结果如下所示:
[1,2,3,4,5]
上述的代码仿写了类似 range() 的类,但是与 range() 又有所不同,除了结果不同以外还包括以下 2 点:
1.iter() 是类中的核心,它返回了迭代器的本身,一个实现了 iter() 方法的对象,就意味着它是可迭代的。
2.实现了 next() 方法,从而使得这个对象是迭代器对象。
接下来我们来看看 range() 本身:
>>> a = range(5)
>>> hasattr(a,'__iter__')
True
>>> hasattr(a,'__next__')
False
>>> print(a)
range(0, 5)
由上面我们就可以看出,其实我们所写的类和 range() 本身还是有很大区别的。
通过上面的内容和我们之前的文章对迭代的讲述,下面我们对迭代器做一个概括:
1.在 Python 中,迭代器是遵循迭代协议的对象。我们可以使用 iter() 从任何序列得到迭代器(exp: list,turple,set and so on)。
2.当自己编写迭代器的类的时候,其中实现 iter() 和 next() 方法,如果没有元素的话,会引发 StopIteration 异常。
3.如果有很多值的话,列表会占用太多的内存,而迭代器则占用的更少,它从第一个元素开始访问,直到所有的元素被访问完结束,只能向前冲,不能后退。
迭代器不仅仅是实用而已,而且也非常的有趣,让我们来看下面的操作:
>>> list1 = [x**x for x in range(3)]
>>> list1
[1, 1, 4]
>>> for i in list1:print(i)
...
1
1
4
>>> for i in list1:print(i)
...
1
1
4
我们在上面重复两次调用列表 list1 进行循环,都是能正常进行的,这个列表相当于一个可以长久使用的东西,可以重复使用。
在 Python 中,除了列表解析式以外,还可以做成元组解析式,方法也是非常的简单:
>>> tuple1 = (x**x for x in range(3))
>>> tuple1
<generator object <genexpr> at 0x0000000001DF16D8>
>>> for i in tuple1:print(i)
...
1
1
4
>>> for i in tuple1:print(i)
...
对于 tuple1,我们可以看到它是一个 generator 对象,关于这个是啥我们先不管,后面我会单独来说的。当我们把它用到循环中的时候,它明显是个一次性用品,再次使用的时候它就什么也不显示了。
>>> type(list1)
<class 'list'>
>>> type(tuple1)
<class 'generator'>
由上面可以看出,list1 和 tuple1 是两种不同的对象,它们之间的区别不仅仅是 tuple1 是一个元组这么简单,它还是 generator。其它的我们先不管,你可以尝试一下在交互模式下输入 dir(tuple1),查看它是否有 iter 和 next,我可以先告诉你,是有的。
既然是有的,那么 tuple1 引用的就是一个迭代器的对象,它的 next() 方法促使它只能向前。
写在之后
迭代器到这就写完了,从内容来看迭代器确实有其过人之处,但是它不是万能的,比如它只能向前,不能回退。还有一个是迭代器并不适合在多线程的环境中对可变集合使用,现在这个东西看起来可能还是有点困难,如果以后有机会写多线程的话,再做解释。
更多内容,欢迎关注公众号「Python空间」,期待和你的交流。
Python 拓展之迭代器的更多相关文章
- Python基础之迭代器和生成器
		阅读目录 楔子 python中的for循环 可迭代协议 迭代器协议 为什么要有for循环 初识生成器 生成器函数 列表推导式和生成器表达式 本章小结 生成器相关的面试题 返回顶部 楔子 假如我现在有一 ... 
- python is、==区别;with;gil;python中tuple和list的区别;Python 中的迭代器、生成器、装饰器
		1. is 比较的是两个实例对象是不是完全相同,它们是不是同一个对象,占用的内存地址是否相同 == 比较的是两个对象的内容是否相等 2. with语句时用于对try except finally 的优 ... 
- python基础之迭代器协议和生成器
		迭代器和生成器补充:http://www.cnblogs.com/luchuangao/p/6847081.html 一 递归和迭代 略 二 什么是迭代器协议 1.迭代器协议是指:对象必须提供一个ne ... 
- python设计模式之迭代器与生成器详解(五)
		前言 迭代器是设计模式中的一种行为模式,它提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示.python提倡使用生成器,生成器也是迭代器的一种. 系列文章 python设计模 ... 
- Python之路迭代器协议、for循环机制、三元运算、列表解析式、生成器
		Python之路迭代器协议.for循环机制.三元运算.列表解析式.生成器 一.迭代器协议 a迭代的含义 迭代器即迭代的工具,那什么是迭代呢? #迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的 ... 
- python基础8 -----迭代器和生成器
		迭代器和生成器 一.迭代器 1.迭代器协议指的是对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退) 2. ... 
- linux和windows下安装python拓展包及requirement.txt安装类库
		python拓展包安装 直接安装拓展包默认路径: Unix(Linux)默认路径:/usr/local/lib/pythonX.Y/site-packagesWindows默认路径:C:\Python ... 
- 【Python基础】迭代器、生成器
		迭代器和生成器 迭代器 一 .迭代的概念 #迭代器即迭代的工具,那什么是迭代呢? #迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值 while True: #只是单 ... 
- Python - 三大器 迭代器,生层器,装饰器
		目录 Python - 三大器 迭代器,生层器,装饰器 一. 容器 二. 可迭代对象(iterable) 三. 迭代器 四. 生成器 五. 装饰器 1. 定义 六. 闭包 Python - 三大器 迭 ... 
随机推荐
- javascript HTML静态页面传值的四种方法
			一:JavaScript静态页面值传递之URL篇能过URL进行传值.把要传递的信息接在URL上.Post.htm 代码如下: <input type="text" name= ... 
- HDU 1114 Piggy-Bank 猪仔储钱罐(完全背包)
			题意: 给定一个存钱罐中要存硬币,知道空罐的重量和欲装满的重量,是否能装入?若能,打印最小价值.(注:能装的硬币重量一定刚刚好,里面的总价值要达到最小) 输入: 包含了T个测试例子,在第一行给出.接下 ... 
- pta 编程题20 旅游规划
			其它pta数据结构编程题请参见:pta 题目 这个最短路径问题只需要求两点之间的最短路径,因而在Dijikstra算法中当求出目标点的最短路径之后跳出循环即可. #include <iostre ... 
- 如何在ABAP Netweaver和CloudFoundry里记录并查看日志
			Netweaver 要记录日志需要有一个checkpoint group,可以自行创建也可以使用标准的.这里我重用标准的group:DEMO_CHECKPOINT_GROUP. tcode SAAB, ... 
- Math类小结
			package com.swift; public class MathDemo { public static void main(String[] args) { // TODO Auto-gen ... 
- Drop it-freecodecamp算法题目
			Drop it 1.要求 丢弃数组(arr)的元素,从左边开始,直到回调函数return true就停止. 第二个参数,func,是一个函数.用来测试数组的第一个元素,如果返回fasle,就从数组中抛 ... 
- 二、C到C++的升级
			C++ 的加强主要表现在:类型的加强.面向对象支持 1.C++改进 C++更强调语言的实用性,所有的变量都可以再需要使用的时候再定义,C语言中的变量都必须在作用域开始的位置定义 int c = 0; ... 
- 可拖拽div
			在开发的时候需要一个可拖拽的prompt弹框.自己写了一个,大概思路为: 1.获取鼠标左键按下移动的起点坐标(x,y). 2.获取div的left和top属性. 3.得到鼠标坐标到左上角的距离(x-t ... 
- 快速搭建lvs + keepalived + nginx
			环境: VIP 192.168.2.224 LVS 192.168.2.217 centos7 nginx1 192.168.2.231 c ... 
- 在windows上搭建镜像yum站的方法
			在windows上搭建镜像yum站的方法(附bat脚本) 分类: 运维基本功,其他 方法一:支持rsync的网站 对于常用的centos.Ubuntu.等使用官方yum源在 http://mi ... 
