03:迭代器和生成器

Posted 情愿为你,画地为牢。

tags:

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

***  迭代器(Iterator)

  ---- 当要返回一个序列或者在循环中执行的函数时,就应该考虑生成器,这些元素将被传递到另一个函数中进行后续处理时,一次返回一个元素能够提高整体性能。  

  ---- 迭代器只不过是一个实现迭代协议的容器对象,它基于两个方法:1)next (python 3 是__next__):返回容器的下一个项目; 2)__iter__ :返回迭代器本身。前者返回迭代过程的下一个集合元素而后者返回一个迭代器对象(如果一个对象没有__iter__方法但定义了__getitem__方法,那么这个对象仍然是可迭代的)。

  ---- python 用for或列表推导式(list comprehension)能够自动为你调用next和iter这两个方法。在for循环中,Python将自动调用工厂函数iter()获得迭代器,自动调用next()获取元素,还完成了检查StopIteration异常的工作。若需手动调用它们,用Python的内建函数iter以及 next。 若c是一个可迭代对象,那么你可以使用iter(c)来访问;如果a是一个迭代器对象,那么请使用next(a)

  ---- 迭代器的实现

 

###1
class count_iterator(object):
    n = 0
    def __iter__(self):
        return self
 
    def next(self):
        y = self.n
        self.n += 1
        return y

counter = count_iterator()
#next(counter)

###2
class SimpleList(object):
    def __init__(self, *items):
        self.items = items
 
    def __getitem__(self, i):
        return self.items[i]

a = SimpleList(1, 2, 3)
it = iter(a)#当Python的内建函数iter将会返回一个对应此对象的迭代器类型,并使用__getitem__方法遍历list的所有元素。如果 StopIteration或IndexError异常被抛出,则迭代停止。
#next(it)
View Code

  --- iter(callable, flagValue)  iter 函数一个鲜为人知的特性是它接受一个可选的 callable 对象和一个标记(结尾)值作为输入参数。 当以这种方式使用的时候,它会创建一个迭代器, 这个迭代器会不断调用 callable 对象直到返回值和标记值相等为止。

 

*** 生成器(Generator)

  ---- yield只适用于函数.当生成器被调用的时候,它会返回一个值给调用者。在生成器内部使用yield来完成这个动作。为了记住yield到底干了什么,最简单的方法是把它当作专门给生成器函数用的特殊的return。调用next()时,生成器函数不断的执行语句,直至遇到yield为止,此时生成器函数的"状态"会被冻结,所有的变量的值会被保留下来,下一行要执行的代码的位置也会被记录,直到再次调用next()继续执行yield之后的语句。next()不能无限执行,当迭代结束时,会抛出StopIteration异常。迭代未结束时,如果你想结束生成器,可以使用close()方法。

 

  ---- 它可以使用空的return语句结束

  ---- 生成器函数可以带参数

  ---- 如果我需要在生成器的迭代过程中接入另一个生成器的迭代(p3.3后实现委托生成器yield from)

def frange(start, stop, increment):
    x = start
    while x < stop:
        yield x
        x += increment

#生成器只能用于迭代操作,一旦生成器函数返回退出,迭代终止。
for n in frange(0, 4, 0.5):
    print(n)
View Code

  ---- 带有外部状态的生成器函数实现

#关于生成器,很容易掉进函数无所不能的陷阱。 如果生成器函数需要跟你的程序其他部分打交道的话(比如暴露属性值,允许通过方法调用来控制等等), 可能会导致你的代码异常的复杂。 如果是这种情况的话,可以考虑使用如下定义类的方式。 在 __iter__() 方法中定义你的生成器不会改变你任何的算法逻辑。 由于它是类的一部分,所以允许你定义各种属性和方法来供用户使用。

from collections import deque

class linehistory:
    def __init__(self, lines, histlen=3):
        self.lines = lines
        self.history = deque(maxlen=histlen)

    def __iter__(self):
        for lineno, line in enumerate(self.lines, 1):
            self.history.append((lineno, line))
            yield line

    def clear(self):
        self.history.clear()
View Code

  ---- 迭代器代替while的无限循环。

 

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

迭代器和生成器

python函数:迭代器和生成器

python函数:迭代器和生成器

(MNIST - GAN) 鉴别器和生成器误差在第一次迭代后接近于零

迭代器和生成器函数

Python中迭代器和生成器的区别与联系