解释:每个生成器都是迭代器,但反之亦然

时间:2017-08-23 09:51:36

标签: python iterator iteration generator

我知道迭代器和生成器是什么。我知道迭代协议,我可以创建它们。我到处读到以下几行:"每个生成器都是迭代器,但反之亦然。"我理解第一部分,但我不理解"反之亦然"部分。生成器对象具有什么,任何简单的迭代器对象都没有?

我读了this question,但它没有解释为什么迭代器不是生成器。只是语法yield解释了差异吗?

提前致谢。

3 个答案:

答案 0 :(得分:3)

  

我知道什么是迭代器,什么是生成器,什么是迭代协议,如何创建它们。

什么是迭代器?

根据词汇表,iterator是“表示数据流的对象”。它有 __ iter __()方法返回自身,并且它有一个 next()方法(在Python 3中是 __ next __())。 next-method负责返回一个值,推进迭代器,并在完成时引发 StopIteration

什么是发电机?

生成器是包含yield的常规Python函数。当调用它时,它返回一个generator-iterator(多种迭代器之一)。

如何创建生成器和迭代器的示例

生成器示例:

>>> def f(x):           # "f" is a generator
        yield x
        yield x**2
        yield x**3

>>> g = f(10)           # calling "f" returns a generator-iterator 
>>> type(f)             # "f" is a regular python function with "yield"
<type 'function'>
>>> type(g)                 
<type 'generator'>
>>> next(g)             # next() gets a value from the generator-iterator
10
>>> next(g)
100
>>> next(g)
1000
>>> next(g)             # iterators signal that they are done with an Exception

Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    next(g)
StopIteration
>>> dir(g)              # generator-iterators have next() and \__iter__
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'next', 'send', 'throw']

使用课程的迭代器:

>>> class Powers:       # "Powers" is a class
        def __init__(self, base):
            self.base = base
            self.exp = 0
        def __iter__(self):
            return self
        def next(self):
            self.exp += 1
            if self.exp > 3:
                raise StopIteration
            return self.base ** self.exp

>>> g = Powers(10)      # calling "Powers" returns an iterator
>>> type(Powers)        # "Power" is a regular python class
<type 'classobj'>
>>> type(g)             # "g" is a iterator instance with next() and __iter__()
<type 'instance'>   
>>> next(g)             # next() gets a value from the iterator
10
>>> next(g)
100
>>> next(g)
1000
>>> next(g)             # iterators signal that they are done with an Exception

Traceback (most recent call last):
  File "<pyshell#34>", line 1, in <module>
    next(g)
StopIteration

来自序列示例的迭代器:

>>> s = 'cat'               
>>> it = iter(s)            # creates an "iterator" from a sequence 
>>> type(s)                 # "s" is a string which is "iterable"
<type 'str'>
>>> type(it)                # An "iterator" with next() and __iter__()
<type 'iterator'>
>>> next(it)
'c'
>>> next(it)
'a'
>>> next(it)
't'
>>> next(it)

Traceback (most recent call last):
  File "<pyshell#43>", line 1, in <module>
    next(it)
StopIteration

比较和结论

迭代器是表示数据流的对象。它有一个 __ iter __()方法和一个 next()方法。

有几种方法可以制作迭代器:

1)调用生成器(使用yield的常规python函数) 2)实例化一个具有 __ iter __()方法和 next()方法的类。

从这里可以看出,生成器只是制作迭代器的众多方法之一(还有其他方法:常规函数上的itertools,iter()和sentinel,等)。

答案 1 :(得分:0)

在python3中,迭代器是一个具有__next__方法的对象。就是这样。

对于要成为生成器的对象,它需要__next__方法,但它也使用yield语句。

因此,两个对象都有__next__方法,迭代器也是如此,但第一个对象并不总是有一个yield语句,因此迭代器不一定是生成器。

实际上,这意味着当您生成生成器时,其所有代码都是而不是立即运行。与此同时,使用更经典的迭代器,您只能运行一代代码。

答案 2 :(得分:-1)

只是生成器是一种特定的迭代器。 他们的两个特殊特征是懒惰的评估(没有预期被请求的价值计算),以及一旦用尽,他们就不能再次迭代了。

另一方面,迭代器只不过是__next__方法和__iter__方法。

所以列表,元组,集合,字典......都是迭代器。 但那些不是生成器,因为它们包含的所有元素都是在容器初始化之后定义和评估的,并且可以多次迭代。

因此,有些迭代器不是生成器。