环境:Python 2.7.11 (v2.7.11:6d1b6a68f775, Dec 5 2015, 20:40:30) [MSC v.1500 64 bit (AMD64)] on win32
迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。 ——《O2O:移动互联网时代的商业革命》
本质上来讲,就是没一次的进化成果是源于前一次的进化后的结果,此方法论抽象为迭代协议。
对于python来说,具备可迭代属性的容器对象分为两类,一类为类序列,如:list,tuple,dict,set,str等等,另一类为,生成器对象(生成器和生成器类)。回归迭代的定义,将可迭代性的对象与循环机制(例如 for)相作用,便可以体现它的可迭代(Iterable)属性,也就是说他们都满足了可迭代协议,而迭代器,既具备可迭代属性(满足迭代协议)还满足next方法(此方法返回可迭代容器的下一个值)。
实例一:(通过iter内建函数,和一个类序列来创建,range函数返回一个列表)
>>> li = range(3)
>>> iter_object = iter(li)
>>> iter_object.next()
0
>>> iter_object.next()
1
>>> iter_object.next()
2
>>> iter_object.next()
Traceback (most recent call last):
File "", line 1, in <module>
StopIteration
ps:序列遍历完时,将抛出StopIteration异常,for循环实际上就是通过捕获这个异常,以停止循环,可见for循环的对象实际上是一个具有可迭代属性的容器
实例二:(文件对象生成的迭代器)
>>> file = open('file.txt')
>>> file.next()
'1\n'
>>> file.next()
'2\n'
>>> file.next()
'3\n'
>>> file.next()
'4\n'
>>> file.next()
'5\n'
>>> file.next()
Traceback (most recent call last):
File "" , line 1, in
StopIteration
实例三:
file = open('file.txt')
for i in file:
print i.strip('\n')
运行结果:(默认会有换行符,需要去除)
1
2
3
4
5
实例四:(字典的內建函数构建迭代器)
dict_obj = {('Poe', 'author'): (1809, 1849, 1976),
('Gaudi', 'architect'): (1852, 1906, 1987),
('Freud', 'psychoanalyst'): (1856, 1939, 1990),
}
字典的一般性遍历如下:
for key in dict_obj.keys():
print 'Name: %s\t Occupation: %s' % key
print 'Birth : %s\t Death: %s\tAlbum: %s\n' % dict_obj[key]
如下,字典的迭代器会遍历他的键,因此如下代码与上一段代码相同
for key in dict_obj:
print 'Name: %s\t Occupation: %s' % key
print 'Birth : %s\t Death: %s\tAlbum: %s\n' % dict_obj[key]
字典的迭代器遍历:如下三个內建的字典方法构建迭代器
for key in dict_obj.iterkeys():
print 'Name: %s\t Occupation: %s' % key
for key in dict_obj.itervalues():
print 'Birth : %s \t Death: %s\tAlbum: %s' % key
for item in dict_obj.iteritems():
print 'Key:%s \t Value:%s ' % item
源码文档解释如下:
def iteritems(self): # real signature unknown; restored from __doc__
""" D.iteritems() -> an iterator over the (key, value) items of D """
pass
def iterkeys(self): # real signature unknown; restored from __doc__
""" D.iterkeys() -> an iterator over the keys of D """
pass
def itervalues(self): # real signature unknown; restored from __doc__
""" D.itervalues() -> an iterator over the values of D """
pass
关于for循环
for i in seq:
do_something_to(i)
实际上是如下工作的,for循环会自动调用迭代器的next()方法,以及监视StopIteration异常,如下:
fetch = iter(seq)
while True:
try
i = fetch.next()
except StopIteration:
break
do_something_to(i)
在迭代可变对象的时候修改可变对象,会发生危险。因为一个序列的迭代器只是记录你当前到达达多少个元素,在迭代时改变元素,更新会立即反映到你所迭代的条目上。
实例五:
定义一个字典
dict_obj = {'a': 1,
'b': 2,
'c': 3,
}
在迭代时修改可迭代对象,如下:
for i in dict_obj:
print 'Key:', i, 'Value:', dict_obj[i]
del dict_obj[i]
运行结果如下:
Key: a Value: 1
Traceback (most recent call last):
File "C:/Users/lenovo/Desktop/pythonexam/Iter_Demo.py", line 128, in <module>
for i in dict_obj:
RuntimeError: dictionary changed size during iteration
实例六:(使用字典的keys方法,它返回一个独立于字典的列表,for的内部实际上是调用iter方法作用于这个列表)
for i in dict_obj.keys():
print 'Key:', i, 'Value:', dict_obj[i]
del dict_obj[i]
print dict_obj
运行结果如下:
Key: a Value: 1
Key: c Value: 3
Key: b Value: 2
{}
实例七:(内建函数xrange返回一个可迭代的对象,这个对象但并不是狭义的迭代器,从广义上说,它满足迭代协议,可以说是另类的迭代器,因为它内部没有构建next()方法。)
list = range(10)
iter = xrange(10)
print list
print iter
运行结果如下:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
xrange(10)
实例八:(用iter()和next()方法构建一个迭代器)
class MyIteration(object):
"""A class for Iteration of mine
"""
def __init__(self,arg):
self.step = arg
def __iter__(self):
return self
def next(self):
if self.step == 0:
raise StopIteration
self.step -= 1
return self.step
iter_object = MyIteration(5)
for i in MyIteration(5):
print iter_object.next()
运行结果:
Traceback (most recent call last):
4
3
2
1
0
File "C:/Users/lenovo/Desktop/pythonexam/Iter_Demo.py", line 166, in <module>
print iter_object.next()
File "C:/Users/lenovo/Desktop/pythonexam/Iter_Demo.py", line 155, in next
raise StopIteration
StopIteration
实例九:(用iter()和next()方法构建一个迭代器,构建一个安全模式的迭代器)
class MyIteration(object):
"""A class for safe Iteration of mine
"""
def __init__(self, setpool, safe=True):
self.safe = safe
self.len = len(setpool)
self.arg = iter(setpool)
def __iter__(self):
return self
def next(self):
for s in range(self.len):
try:
if self.arg == 0:
break
else:
return self.arg.next()
except StopIteration:
getattr(self, '_is_error')()
break
def _is_error(self):
if not self.safe:
raise StopIteration
else:
pass
l = range(5)
iter_object = MyIteration(l)
for i in range(10):
print iter_object.next()
运行结果如下:
0
1
2
3
4
None
None
None
None
None