34

迭代器和生成器有什么区别?

4

9 回答 9

43

迭代器一次遍历一个集合。

生成器生成一个序列,一次一个项目。

例如,您可能会迭代生成器的结果......

于 2009-06-20T21:20:34.977 回答
39

生成器是迭代器,但并非所有迭代器都是生成器。

迭代器通常是具有从流中获取下一个元素的next方法的东西。生成器是与函数绑定的迭代器。

例如 python 中的生成器:

def genCountingNumbers():
  n = 0
  while True:
    yield n
    n = n + 1

这样做的好处是您不需要在内存中存储无限的数字来迭代它们。

您可以像使用任何迭代器一样使用它:

for i in genCountingNumbers():
  print i
  if i > 20: break  # Avoid infinite loop

您还可以遍历数组:

for i in ['a', 'b', 'c']:
  print i
于 2009-06-20T21:19:35.150 回答
9

这里有太多的 Python,也有太多人说生成器是实现无限迭代器的唯一方法。这是我提到的用 C# 实现的示例(所有自然数的平方)。ExplicitSquares 显式实现了一个迭代器(在 C# 中称为 IEnumerator)。ImplicitSquares 使用生成器来做同样的事情。两者都是无限迭代器并且没有支持集合。唯一的区别是状态机是拼写出来的,还是使用生成器。

using System.Collections;
using System.Collections.Generic;
using System;

class ExplicitSquares : IEnumerable<int>
{
    private class ExplicitSquaresEnumerator : IEnumerator<int>
    {
        private int counter = 0;

        public void Reset()
        {
            counter = 0;
        }

        public int Current { get { return counter * counter; }}

        public bool MoveNext()
        {
            counter++;
            return true;
        }

        object IEnumerator.Current { get { return Current; } }

        public void Dispose(){}
    }

    public IEnumerator<int> GetEnumerator()
    {
        return new ExplicitSquaresEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

class ImplicitSquares : IEnumerable<int>
{
    public IEnumerator<int> GetEnumerator()
    {
        int counter = 1;
        while(true)
        {
            int square = counter * counter;
            yield return square;
            counter++;
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

public class AllSquares
{
    private static readonly int MAX = 10;

    public static void Main()
    {
        int i = 0;
        foreach(int square in new ExplicitSquares())
        {
            i++;
            if(i >= MAX)
                break;
            Console.WriteLine(square);
        }

        Console.WriteLine();

        int j = 0;
        foreach(int square in new ImplicitSquares())
        {
            j++;
            if(j >= MAX)
                break;
            Console.WriteLine(square);
        }
    }
}
于 2009-06-21T05:28:20.967 回答
5

生成器是迭代器的实现。它通常是一个例程,它为调用者产生多个值,而不是一个。

在c#中

// yield-example.cs
using System;
using System.Collections;
public class List
{
    public static IEnumerable Power(int number, int exponent)
    {
        int counter = 0;
        int result = 1;
        while (counter++ < exponent)
       {
            result = result * number;
            yield return result;
    }
}

static void Main()
{
    // Display powers of 2 up to the exponent 8:
    foreach (int i in Power(2, 8))
    {
        Console.Write("{0} ", i);
    }
}
}

查看维基百科的条目

于 2009-06-20T21:20:01.717 回答
5

生成器是一个特殊的函数,它可以作为一个迭代器,每次调用它都会返回一个值。因为它是一个函数,它可以按需计算每个值。而且因为它很特殊,它可以记住上次调用时的状态,所以生成的代码看起来很简单。

例如,python中的这个生成器将产生一个整数序列

def integers():
    int n = 0
    while True:
        yield n
        n += 1

这个例子中最重要的是yield n语句。该函数将返回该值,并且下次调用它时,它将从该点继续。

这个链接对python中的生成器有更长的解释: link text

于 2009-06-20T21:39:02.163 回答
4

(来自javascript useland,但与所有其他人一样)

插入器是具有 .next() 函数的对象

生成器是一个函数,一旦被调用,就会产生一个迭代器,它是一个迭代器的工厂。

在 javascript 中,生成器函数需要特殊的语法函数 *(){} 并使用 yield 关键字

请参阅 MDN:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators

于 2016-08-21T07:38:39.777 回答
1

通常迭代器遍历现有序列(例如数组或列表),生成器在每次请求时计算一个新值。

于 2009-06-20T21:21:09.093 回答
1

迭代器用于迭代集合中的对象,可以是数组、链表、树、哈希映射等。你有一堆对象,你想对它们中的每一个做一些事情。

生成器不只是从一些有限的对象集合中返回项目。相反,它会即时生成它们。您可以将其概念化为对在迭代时创建的集合的迭代器,并且可能没有有限的大小。

例如,您可以有一个生成器,它可以输出从 2 到无穷大的素数。您不可能拥有“所有素数”的集合并使用迭代器对其进行迭代。你需要一个发电机。

或者你可以有一个生成器,它接受一个整数并一次产生那个数字的因子。在这里,生成器将使您受益,因为您可以一一检查这些因素,而无需预先为所有因素分配内存。它还允许您在生成它们时使用它们,而不必预先生成整个列表,这可能比您喜欢的要慢。这是 Python 中此类生成器的示例:

def factors(n):
    for i in xrange(1, n+1):
        if n % i == 0:
            yield i

for n in factors(1234567890):
    print n

如果你运行它,你可以看到计算出来的因子。我们实际上不需要在内存中维护所有因素的完整列表。

于 2009-06-20T21:26:46.853 回答
0

迭代器通常用于在项目集合中移动。通常有 MoveNext() 和 Current() 方法。MoveNext() 会将指针移动到下一个集合项(如果可能)并根据成功返回真/假。Current() 将提供实际值。

生成器是迭代器的实现,但它不是指向预先存在的集合,而是在每次 MoveNext() 调用时创建新项目。

于 2009-06-20T21:22:20.620 回答