环境: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 "<input>", line 1, in <module> StopIterationps:序列遍历完时,将抛出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 "<stdin>", line 1, in <module> 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