码迷,mamicode.com
首页 > 编程语言 > 详细

python 迭代器与生成器 详解

时间:2016-05-07 09:18:18      阅读:245      评论:0      收藏:0      [点我收藏+]

标签:

在python中,我们经常使用for循环来遍历各种集合,例如最常用的有list,dict等等,这些集合都是可迭代对象。我们先来了解一下python中的迭代器(Iterator)。

一、迭代器

顾名思义,迭代器,自然就是用来做迭代用的(好像是废话)。以list为例,我们用list,最多的情况就是用来做循环了(循环就是迭代嘛)

>>> list = [1,2,3]
>>> dir(list)
[‘__add__‘, ‘__class__‘, ‘__contains__‘, ‘__delattr__‘, ‘__delitem__‘, ‘__delslice__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__getitem__‘, ‘__getslice__‘, ‘__gt__‘, ‘__hash__‘, ‘__iadd__‘, ‘__imul__‘, ‘__init__‘, ‘__iter__‘, ‘__le__‘, ‘__len__‘, ‘__lt__‘, ‘__mul__‘, ‘__ne__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__reversed__‘, ‘__rmul__‘, ‘__setattr__‘, ‘__setitem__‘, ‘__setslice__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘append‘, ‘count‘, ‘extend‘, ‘index‘, ‘insert‘, ‘pop‘, ‘remove‘, ‘reverse‘, ‘sort‘]

list就有__iter__方法。如果调用此方法,则会返回一个迭代器

>>> it = list.__iter__()
>>> it
<listiterator object at 0x10fa12950>
>>> dir(it)
[‘__class__‘, ‘__delattr__‘, ‘__doc__‘, ‘__format__‘, ‘__getattribute__‘, ‘__hash__‘, ‘__init__‘, ‘__iter__‘, ‘__length_hint__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘next‘]

所谓迭代器,是指具有next方法的对象。注意调用next方式的时候,不需要任何参数。调用next方法时,迭代器会返回它的下一个值。如果迭代器没有值返回,则会抛出StopIteration的异常。

>>> it.next()
1
>>> it.next()
2
>>> it.next()
3
>>> it.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

有的同学会问,我们用list用得好好的,为什么要用什么iterator?因为list是一次性获得所有值,如果这个列表很大,需要占用很大内存空间,甚至大到内存装载不下;而迭代器则是在迭代(循环)中使用一个计算一个,对内存的占用显然小得多。

用迭代器实现Fibonacci数列

#!/usr/bin/env python
#coding:utf-8

‘‘‘
Created on 2016年5月6日

@author: lei.wang
‘‘‘

class Fibonacci(object):
    def __init__(self):
        self.a = 0
        self.b = 1

    def next(self):
        self.a,self.b = self.b,self.a + self.b
        print self.a
        return self.a

    def __iter__(self):
        return self

if __name__ == ‘__main__‘:
    fib = Fibonacci()
    for n in fib:
        if n > 10:
            #print n
            break

刚才我们讲的都是从列表转为迭代器,那从迭代器能变成列表么?答案是当然可以,请看:

#!/usr/bin/env python
#coding:utf-8

‘‘‘
Created on 2016年5月6日

@author: lei.wang
‘‘‘

class MyIterator(object):
    index = 0

    def __init__(self):
        pass

    def next(self):
        self.index += 1
        if self.index > 10:
            raise StopIteration
        return self.index

    def __iter__(self):
        return self

if __name__ == ‘__main__‘:
    my_interator = MyIterator()
    my_list = list(my_interator)
    print my_list
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

二、生成器

当我们调用一个普通的python函数时(其实不光是python函数,绝大部分语言的函数都是如此),一般都是从函数的第一行开始执行,直到遇到return语句或者异常或者函数的最后一行。这样,函数就将控制权交还与调用者,函数中的所有工具以及局部变量等数据都将丢失。再次调用这个函数的时候,所有的局部变量,堆栈信息都将重新创建,跟之前的调用再无关系。

有时候我们并不希望函数只返回一个值,而是希望返回一个序列,比如前面的fibonacci序列。要做到这一点,这种函数需要能够保存自己的工作状态。这样的话,就不能使用我们通常所使用的return语句,因为一旦使用return语句,代码执行的控制权就交给了函数被调用的地方,函数的所有状态将被清零。在这种情况下,我们就需要使用yield关键字。

python 迭代器与生成器 详解

标签:

原文地址:http://blog.csdn.net/bitcarmanlee/article/details/51335055

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!