Python拾遗之迭代器和生成器(一)

xiaoxiao2021-02-27  331

迭代器与生成器(一)

环境: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> 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 "<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
转载请注明原文地址: https://www.6miu.com/read-4414.html

最新回复(0)