迭代器和生成器之间的区别是什么?举一些例子来说明你在什么时候使用每种情况会很有帮助。


当前回答

无代码4行小抄:

A generator function is a function with yield in it.

A generator expression is like a list comprehension. It uses "()" vs "[]"

A generator object (often called 'a generator') is returned by both above.

A generator is also a subtype of iterator.

其他回答

这篇文章涵盖了两者之间的许多细节差异,但想在两者之间的概念差异上添加一些东西:

[…GoF书中定义的迭代器从集合中检索项,而生成器可以“凭空”生成项。这就是为什么斐波那契序列生成器是一个常见的例子:无限级数的数字不能存储在一个集合中。

Ramalho,卢西亚诺。流利的Python(第415页)。O ' reilly媒体。Kindle版。

当然,它并没有涵盖所有的方面,但我认为它给出了一个很好的概念,当一个人是有用的。

我用一种非常简单的方式专门为Python新手编写,尽管Python在本质上做了很多事情。

让我们从最基本的开始:

考虑一个列表,

l = [1,2,3]

让我们写一个等效函数:

def f():
    return [1,2,3]

打印(l)的O /p: [1,2,3] & O /p打印(f()): [1,2,3]

让列表l可迭代:在python中,列表总是可迭代的,这意味着你可以在任何你想要的时候应用迭代器。

让我们在list上应用迭代器:

iter_l = iter(l) # iterator applied explicitly

让我们把一个函数设为可迭代的,也就是说,写一个等效的生成器函数。 在python中,只要你引入关键字yield;它变成了一个生成器函数,迭代器将隐式应用。

注意:每个生成器在应用隐式迭代器时总是可迭代的,这里隐式迭代器是关键 因此生成器函数将是:

def f():
  yield 1 
  yield 2
  yield 3

iter_f = f() # which is iter(f) as iterator is already applied implicitly

如果你观察到,一旦你让函数f成为一个生成器,它就已经是iter(f)

Now,

L是列表,在应用迭代器方法iter后,它变成, iter(左) F已经是iter(F),在应用迭代器方法“iter”它 变成iter(iter(f))也就是iter(f)

这有点像你将int类型转换为int(x)它已经是int类型并且它将保持int(x)

例如o/p:

print(type(iter(iter(l))))

is

<class 'list_iterator'>

别忘了这是Python而不是C或c++

因此,由上述解释得出的结论是:

列出l ~= iter(l) 生成函数f == iter(f)

生成器函数,生成器对象,生成器:

Generator函数就像Python中的常规函数一样,但它包含一个或多个yield语句。Generator函数是一个很好的工具,可以尽可能简单地创建Iterator对象。generator函数返回的Iterator对象也称为generator对象或generator。

在这个例子中,我创建了一个Generator函数,它返回一个Generator对象< Generator对象fib at 0x01342480>。就像其他迭代器一样,Generator对象可以在for循环中使用,也可以与从Generator返回下一个值的内置函数next()一起使用。

def fib(max):
    a, b = 0, 1
    for i in range(max):
        yield a
        a, b = b, a + b
print(fib(10))             #<generator object fib at 0x01342480>

for i in fib(10):
    print(i)               # 0 1 1 2 3 5 8 13 21 34


print(next(myfib))         #0
print(next(myfib))         #1
print(next(myfib))         #1
print(next(myfib))         #2

因此,生成器函数是创建Iterator对象的最简单方法。

迭代器:

每个生成器对象都是迭代器,反之亦然。如果自定义迭代器对象的类实现了__iter__和__next__方法(也称为迭代器协议),则可以创建自定义迭代器对象。

然而,使用生成器函数来创建迭代器要容易得多,因为它们简化了迭代器的创建,但是自定义迭代器给了你更多的自由,你也可以根据你的需求实现其他方法,如下面的例子所示。

class Fib:
    def __init__(self,max):
        self.current=0
        self.next=1
        self.max=max
        self.count=0

    def __iter__(self):
        return self

    def __next__(self):
        if self.count>self.max:
            raise StopIteration
        else:
            self.current,self.next=self.next,(self.current+self.next)
            self.count+=1
            return self.next-self.current

    def __str__(self):
        return "Generator object"

itobj=Fib(4)
print(itobj)               #Generator object

for i in Fib(4):  
    print(i)               #0 1 1 2

print(next(itobj))         #0
print(next(itobj))         #1
print(next(itobj))         #1

可迭代对象是可以(自然地)迭代的对象。然而,要做到这一点,你将需要一个类似迭代器对象的东西,是的,术语可能令人困惑。可迭代对象包括__iter__方法,该方法将返回可迭代对象的迭代器对象。

迭代器对象是一个实现迭代器协议的对象——一组规则。在这种情况下,它必须至少有这两个方法:__iter__和__next__。__next__方法是一个提供新值的函数。__iter__方法返回迭代器对象。在更复杂的对象中,可能有单独的迭代器,但在更简单的情况下,__iter__返回对象本身(通常返回self)。

一个iterable对象是一个列表对象。它不是一个迭代器,但它有一个__iter__方法,返回一个迭代器。你可以直接以things.__iter__()的形式调用这个方法,或者使用iter(things)。

如果你想遍历任何集合,你需要使用它的迭代器:

things_iterator = iter(things)
for i in things_iterator:
    print(i)

然而,Python会自动使用迭代器,这就是为什么你从来没有看到上面的例子。相反,你可以这样写:

for i in things:
    print(i)

自己编写迭代器可能很乏味,所以Python有一个更简单的选择:生成器函数。生成器函数不是普通的函数。不是遍历代码并返回最终结果,而是延迟代码,函数立即返回一个生成器对象。

生成器对象类似于迭代器对象,因为它实现了迭代器协议。这对于大多数目的来说已经足够好了。在其他答案中有许多生成器的例子。

简而言之,迭代器是一个对象,它允许您迭代另一个对象,无论它是一个集合还是其他一些值的来源。生成器是一个简化的迭代器,它或多或少完成相同的工作,但更容易实现。

通常情况下,如果你只需要发电机,你会选择发电机。但是,如果您正在构建一个更复杂的对象,其中包含其他特性之间的迭代,则应该使用迭代器协议。

强烈推荐Ned Batchelder的迭代器和生成器示例

一个没有生成器的方法,它对偶数进行处理

def evens(stream):
   them = []
   for n in stream:
      if n % 2 == 0:
         them.append(n)
   return them

而通过使用发电机

def evens(stream):
    for n in stream:
        if n % 2 == 0:
            yield n

我们不需要任何列表或返回语句 有效的大/无限长的流…它只是走动并产生值

调用evens方法(生成器)和往常一样

num = [...]
for n in evens(num):
   do_smth(n)

发电机也用于打破双环

迭代器

满页的书是可迭代对象,书签是可迭代对象 迭代器

而这个书签除了下一步移动什么也做不了

litr = iter([1,2,3])
next(litr) ## 1
next(litr) ## 2
next(litr) ## 3
next(litr) ## StopIteration  (Exception) as we got end of the iterator

使用生成器…我们需要一个函数

使用迭代器…我们需要next和iter

如前所述:

Generator函数返回一个迭代器对象

Iterator的全部好处:

每次在内存中存储一个元素