我知道迭代器和生成器是什么。我知道迭代协议,我可以创建它们。我到处读到以下几行:"每个生成器都是迭代器,但反之亦然。"我理解第一部分,但我不理解"反之亦然"部分。生成器对象具有什么,任何简单的迭代器对象都没有?
我读了this question,但它没有解释为什么迭代器不是生成器。只是语法yield
解释了差异吗?
提前致谢。
答案 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__
方法。
所以列表,元组,集合,字典......都是迭代器。 但那些不是生成器,因为它们包含的所有元素都是在容器初始化之后定义和评估的,并且可以多次迭代。
因此,有些迭代器不是生成器。