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

迭代器与生成器(一)

环境: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

你可能感兴趣的:(Python开发,python高级编程)