详解Python迭代和迭代器


Posted in Python onMarch 28, 2016

我们将要来学习python的重要概念迭代和迭代器,通过简单实用的例子如列表迭代器和xrange。

可迭代

一个对象,物理或者虚拟存储的序列。list,tuple,strins,dicttionary,set以及生成器对象都是可迭代的,整型数是不可迭代的。如果你不确定哪个可迭代哪个不可以,你需要用python内建的iter()来帮忙。

>>> iter([1,2,3])
<listiterator object at 0x026C8970>

>>> iter({1:2, 2:4})
<dictionary-keyiterator object at 0x026CC1B0>

>>> iter(1234)
Traceback (most recent call last):
 File "<pyshell#145>", line 1, in <module>
  iter(1234)
TypeError: 'int' object is not iterable

iter()为list返回了listiterator对象,为dictionary返回了dictionary-keyiterator对象。类似对其他可迭代类型也会返回迭代器对象。

iter()用在自定义的类型会怎样呢?我们先自己定义一个String类:

class String(object):
 def __init__(self, val):
  self.val = val
 def __str__(self):
  return self.val
st = String('sample string')

那么,st是可迭代的吗?

>>> iter(st)

TypeError: 'String' object is not iterable

你可能会有几个问题要问:

怎么让自定义的类型可迭代?
iter()究竟做了些什么?
让我们补充String类来找找答案

class String(object):
  def __init__(self, val):
    self.val = val
  def __str__(self):
    return self.val
  def __iter__(self):
    print "This is __iter__ method of String class"
    return iter(self.val) #self.val is python string so iter() will return it's iterator
>>> st = String('Sample String')
>>> iter(st)
This is __iter__ method of String class
<iterator object at 0x026C8150>

在String类中需要一个'__iter__'方法把String类型变成可迭代的,这就是说'iter'内部调用了'iterable.__iter__()'

别急,不是只有增加'__iter()'方法这一种途径

class String(object):
  def __init__(self, val):
    self.val = val
  def __str__(self):
    return self.val
  def __getitem__(self, index):
    return self.val[index]
>>> st = String('Sample String')
>>> iter(st)
<iterator object at 0x0273AC10>

‘itr'也会调用'iterable.__getitem__()',所以我们用'__getitem__'方法让String类型可迭代。

如果在String类中同时使用'__iter__()'和'__getitem__()',就只有'__iter__'会起作用。

自动迭代

for循环会自动迭代

for x in iterable:
  print x

我们可以不用for循环来实现吗?

def iterate_while(iterable):
  index = 0
  while(i< len(iterable)):
    print iterable[i]
    i +=1

这样做对list和string是管用的,但对dictionary不会奏效,所以这绝对不是python式的迭代,也肯定不能模拟for循环的功能。我们先看迭代器,等下回再过头来。

迭代器

关于迭代器先说几条………..

1. 迭代器对象在迭代过程中会会产生可迭代的值,`next()`或者`__next()__`是迭代器用来产生下一个值的方法。
2. 它会在迭代结束后发出StopIteration异常。
3. `iter()`函数返回迭代器对象
4. 如果`iter()`函数被用在迭代器对象,它会返回对象本身
我们试一试模仿for循环

def simulate_for_loop(iterable):
  it = iter(iterable)
  while(True):
 try:
   print next(it)
 except StopIteration:
   break
>>> simulate_for_loop([23,12,34,56])
23
12
34
56

前面我们看过了iterable类,我们知道iter会返回迭代器对象。

现在我们试着理解迭代器类的设计。

class Iterator:
  def __init__(self, iterable)
    self.iterable = iterable
  .
  .
  def __iter__(self): #iter should return self if called on iterator
    return self
  def next(self): #Use __next__() in python 3.x
    if condition: #it should raise StopIteration exception if no next element is left to return
      raise StopIteration

我们学了够多的迭代和迭代器,在python程序中不会用到比这更深的了。

但是为了学习的目的我们就到这儿。。。。

列表迭代器

你可能会在面试中写这个,所以打起精神来注意了

class list_iter(object):
  def __init__(self, list_data):
    self.list_data = list_data
    self.index = 0
  def __iter__(self):
    return self
  def next(self):  #Use __next__ in python 3.x
    if self.index < len(self.list_data):
      val = self.list_data[self.index]
      self.index += 1 
      return val
    else:
      raise StopIteration()

我们来用`list_iter`自己定义一个列表迭代器

class List(object):
  def __init__(self, val):
    self.val = val
  def __iter__(self):
    return list_iter(self.val)
>>> ls = List([1,2,34])
>>> it = iter(ls)
>>> next(it)
1
>>> next(it)
2
>>> next(it)
34
>>> next(it)

Traceback (most recent call last):
 File "<pyshell#254>", line 1, in <module>
  next(it)
 File "<pyshell#228>", line 13, in next
  raise StopIteration()
StopIteration

xrange

从一个问题开始——xrange是迭代还是迭代器?

我们来看看

>>> x = xrange(10)
>>> type(x)
<type 'xrange'>

几个关键点:

1. `iter(xrange(num))`应该被支持
2. 如果`iter(xrange(num))`返回同样的对象(xrange类型)那xrange就是迭代器
3. 如果`iter(xrange(num))`返回一个迭代器对象那xrange就是迭代

>>> iter(xrange(10))
<rangeiterator object at 0x0264EFE0>

它返回了rangeiterator,所以我们完全可以叫它迭代器。

让我们用最少的xrange函数实现自己的xrange

xrange_iterator

class xrange_iter(object):
  def __init__(self, num):
    self.num = num
    self.start = 0
  def __iter__(self):
    return self
  def next(self):
    if self.start < self.num:
      val = self.start
      self.start += 1
      return val
    else:
      raise StopIteration()

my xrange

class my_xrange(object):
  def __init__(self, num):
    self.num = num
  def __iter__(self):
    return xrange_iter(self.num)
>>> for x in my_xrange(10):
 print x,

0 1 2 3 4 5 6 7 8 9

以上就是本文的全部内容,希望对大家学习掌握Python迭代和迭代器有所帮助。

Python 相关文章推荐
把MySQL表结构映射为Python中的对象的教程
Apr 07 Python
Python调用命令行进度条的方法
May 05 Python
python单元测试unittest实例详解
May 11 Python
Python实现将一个正整数分解质因数的方法分析
Dec 14 Python
python 寻找优化使成本函数最小的最优解的方法
Dec 28 Python
wtfPython—Python中一组有趣微妙的代码【收藏】
Aug 31 Python
Python3.5多进程原理与用法实例分析
Apr 05 Python
Numpy对数组的操作:创建、变形(升降维等)、计算、取值、复制、分割、合并
Aug 28 Python
Python中BeautifuSoup库的用法使用详解
Nov 15 Python
python实例化对象的具体方法
Jun 17 Python
python中Array和DataFrame相互转换的实例讲解
Feb 03 Python
numpy实现RNN原理实现
Mar 02 Python
Python读大数据txt
Mar 28 #Python
Python常用的爬虫技巧总结
Mar 28 #Python
Python对数据库操作
Mar 28 #Python
Python字符串切片操作知识详解
Mar 28 #Python
python Django框架实现自定义表单提交
Mar 25 #Python
python Django批量导入数据
Mar 25 #Python
python Django批量导入不重复数据
Mar 25 #Python
You might like
从零开始的异世界生活:第二季延期后,B站上架了第二部剧场版
2020/05/06 日漫
在php中取得image按钮传递的name值
2006/10/09 PHP
PHP小教程之实现双向链表
2014/06/12 PHP
php获取url参数方法总结
2014/11/13 PHP
php中http与https跨域共享session的解决方法
2014/12/20 PHP
浅谈php错误提示及查错方法
2015/07/14 PHP
centos+php+coreseek+sphinx+mysql之一coreseek安装篇
2016/10/25 PHP
用PHP将Unicode 转化为UTF-8的实现方法(推荐)
2017/02/08 PHP
php中str_pad()函数用法分析
2017/03/28 PHP
javascript 继承实现方法
2009/08/26 Javascript
利用毫秒减值计算时长的js代码
2013/09/22 Javascript
jquery获取元素值的方法(常见的表单元素)
2013/11/15 Javascript
js实现动态改变字体大小代码
2014/01/02 Javascript
实现checkbox全选、反选、取消JavaScript小脚本异常
2014/04/10 Javascript
防止登录页面出现在frame中js代码
2014/07/22 Javascript
IE6浏览器中window.location.href无效的解决方法
2014/11/20 Javascript
js闭包所用的场合以及优缺点分析
2015/06/22 Javascript
详解VueJs前后端分离跨域问题
2017/05/24 Javascript
NodeJs使用Mysql模块实现事务处理实例
2017/05/31 NodeJs
JavaScript中Object值合并方法详解
2017/12/22 Javascript
解决vue+element 键盘回车事件导致页面刷新的问题
2018/08/25 Javascript
Vue实现剪贴板复制功能
2019/12/31 Javascript
Python设置在shell脚本中自动补全功能的方法
2018/06/25 Python
Python3实现的判断环形链表算法示例
2019/03/07 Python
python字符串反转的四种方法详解
2019/12/02 Python
selenium+python自动化78-autoit参数化与批量上传功能的实现
2021/03/04 Python
Reebok官方旗舰店:美国知名健身品牌锐步
2019/01/07 全球购物
《王二小》教学反思
2014/02/27 职场文书
公司中层干部的自我评价分享
2014/03/01 职场文书
学生鉴定评语大全
2014/05/05 职场文书
优秀学生党员先进事迹材料
2014/05/29 职场文书
2014乡党委副书记党建工作汇报材料
2014/11/02 职场文书
实习指导教师评语
2014/12/30 职场文书
民主评议党员个人总结
2015/02/13 职场文书
anaconda python3.8安装后降级
2021/06/11 Python
MySQL 亿级数据导入导出及迁移笔记
2021/06/18 MySQL