Python 迭代器&生成器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 迭代器&生成器相关的知识,希望对你有一定的参考价值。

迭代器

  任何一个类,只要其实现了__iter__方法,就算是一个可迭代对象。可迭代对象的__iter__方法返回的对象是迭代器,迭代器类需要实现next方法。一般来说,实现了__iter__方法的类肯定还会顺便实现next方法,也就是说这个类既是一个可迭代对象也是个迭代器。

  一个迭代器ite可用ite.next()方法来返回其定义好的以某种算法找到的下一个元素,内建的iter(...)函数可把可迭代对象转化为迭代器。最常见的利用可迭代对象和迭代器的就是for语句了:

  for item in iterable这句话,首先调用了iterable这个对象的__iter__方法,返回一个迭代器(which在很多情况下就是iterable对象本身,就像上面说的,一个可迭代对象的类趋向于实现next让它成为自身的迭代器)。根据迭代器的next方法的算法一个接一个的提供值,把这个值赋给item,然后让item去进行循环体的操作。

  如果要自定义一个迭代器or可迭代对象的类,可以这样来:

class test(object):
    def __init__(self,num=10):
        self.num = num
        self.li = range(num)
        self.count = 0

    def __iter__(self):    #一般做法就是让__iter__直接返回自身就好了
        return self

    def next(self):
        try:
            if self.count == 0:
                return self.li[0]
            elif self.count <= self.num-1:
                return self.li[self.count]
            else:
                raise StopIteration    #调用迭代器的语句并不知道迭代什么时候才能完成,其往往是按照next给出的逻辑一直迭代下去直到出错。
                        #想让迭代器在某个边际下停止继续迭代的话,就需要在合适的条件时raise StopIteration来停止迭代。
                       #这个raise出来的并不是会输出到stderr的异常或错误,而是让调用迭代器的语句知道,可以不用再调用next方法来获取下一个值了
finally: self.count+=2 #这里还有一个比较tricky的,和迭代器本身没啥关系的点。。之前我在写count+=2的时候发现,无论写哪里都不太好。
                 #因为按照现有语句的逻辑,最好是在next方法返回值后count能再加一次2,这样下次进next万一超过了num-1的限制就可以不用再return。
                 # 但是一般而言,return之后的语句在本次调用函数的过程中时肯定不会再被执行了,除了try/finally结构。
                 # 就是说,finally中的语句,即便是在return执行了之后还是会被执行的。这点比较难想到!
if __name__ == __main__: test = test() for item in test: print item

 

生成器

  任何带有yield语句的函数都是生成器。yield通常用在这样一个场景:在(多重)循环中,每遍历出一个单位,不立刻对其做处理,而是统一整合在一起再来处理。

  调用具有生成器性质的函数后,返回的是一个可迭代对象(一般函数有return语句的话返回的就是一个实在的东西)。所以可以对他进行for item in 生成器 的操作。

  比如如下示例:

def flatten(nested_thing):
    for element in netsed_thing:
        if not isinstance(element,list):
            yield element
        else:
            for subelement in flatten(element):
                yield element

nested = [[1,2],[3,4],5,[[6,7],8]]
result = list(flatten(nested))
print result

#结果是[1,2,3,4,5,6,7,8]

  这个函数的功能是把很多重嵌套的列表展开铺平成一个列表。可以看到flatten函数是一个生成器,返回一个可迭代对象(所以可以在递归那里有for subelement in flatten(element))。从这个示例中我们还可以看出,在递归中,yield掉的东西是不分递归层级统一放置的,所以在第一层级yield到的5,和第二层级(一次递归)yield到的1234等,以及第三层级(二次递归)yield到的东西全部都放到了同一个可迭代对象里面了。

  其实很多时候,生成器没有这个必要(或者说看起来很难懂所以换种简单的方式?= =)完全可以在得到结果之前用result = [],然后在yield语句的地方换成result.append(element),也可以得到相同的结果哈。






以上是关于Python 迭代器&生成器的主要内容,如果未能解决你的问题,请参考以下文章

python高级之生成器&迭代器

python 装饰器&生成器&迭代器

python开发函数进阶:可迭代的&迭代器&生成器

Python-迭代器&生成器&装饰器&软件目录结构规范-Day5

python开发函数进阶:可迭代的&迭代器&生成器

Python 迭代器&生成器