【Python】迭代器(iterator) vs 生成器(generator)

来源:互联网 发布:ati mac驱动放在哪里 编辑:程序博客网 时间:2024/06/04 23:31

迭代器(iterator)

在介绍迭代器之前还有一种iterable对象需要简单的说明。对于iterator和iterable是两个不同的概念。

iterable

  • iterable是含有__iter__方法或者__getitem__ 的一个对象,当你想实现一个iterable对象的时候,通过实现__iter__方法返回一个iterator而不是iterable。检查一个对象是不是iterable对象一般是通过catch异常的方式去检查,虽然这个方式有点挫;另外一种是检查是否是容器类中的Itreaable对象if isinstance(e, collections.Iterable)。对于一个iterable的对象可以通过调用iter方法返回一个iterator对象,然后进行for loop访问。
class Iterable_:   def __iter__(self):       return iter([1, 2, 3]) it = iter((Iterable_()))for i in it:     print "iterable:" + str(i)#输出iterable:1iterable:2iterable:3

iterator

  • 迭代器肯定是iterable类型的对象,它是包含有next(Python 2) 方法或者__next__(Python 3) 方法和__iter__(返回self)方法的一个特殊对象,可以对这样一个对象进行for loop循环访问。
  • 对于实现next方法需要注意的是,当没有下一个元素的时候必须抛出StopIteration异常
  • 当遍历一个迭代器的时候,它会修改内部状态,导致你只能向前获取下一个元素,不能通过迭代器访问后面一个元素;也就是说当你通过迭代器访问了一个元素以后,在当前循环中不能后退继续访问该元素了,除非你重新生产迭代器对象进行遍历。
  • 另外需要注意的是在迭代器中next方法是return下一个元素的值,不像下面介绍的生成器yield一个元素。
class Iterator_:   def __init__(self, s, e):        self.current = s        self.end = e    def __iter__(self):       return self   def next(self):       if self.current < self.end:           self.index = self.current           self.current += 1           return self.index       else:           raise StopIterationit = Iterator_(5, 8)for i in it:     print "iterator:" + str(i)#never printfor i in it:     print "second iterator:" + str(i)#print againit = Iterator_(5, 8)for i in it:     print "second iterator:" + str(i)#输出iterator:5iterator:6iterator:7second iterator:5second iterator:6second iterator:7

生成器(generator)


对于一个生成器它一定是一个迭代器,可以通过for loop进行访问其中的元素,但是一个迭代器却很明显的不一定是生成器
定义迭代器有两种方式,第一个是使用yield关键词,另外一个是生成器表达式"()"。对于一个方法在方法体里加上yield关键词就变成了生成器。yield作用就是返回一个生成器,它会保存当前函数状态,记录下一次函数被调用next的时候运行状态。当函数没有下一次运行状态的时候,再继续调用next方法,这个时候StopIteration异常就被抛出。
print "generator"#first way my_generator = (x for x in range(3))for i in my_generator:    print i#second waydef Generator_(l):   n = 0    size = len(l)   while n < size:       yield l[n]          n += 1ge = Generator_([1, 2, 3]) for g in ge:     print "generator:" + str(g)

因为生成器是一个迭代器,所以迭代器具有的特性,生成器肯定会具有的。比如只能向前遍历等。当然除了迭代器特性之外,生成器还有自己的方法。比如send方法等。通过send可以定义当前生成器中的值。
1 0
原创粉丝点击