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

时间:2009-06-20 21:13:09

标签: iterator generator

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

9 个答案:

答案 0 :(得分:37)

iterator一次遍历一个集合。

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

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

答案 1 :(得分:34)

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

迭代器通常是具有 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

答案 2 :(得分:6)

这里有太多的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);
        }
    }
}

答案 3 :(得分: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);
    }
}
}

See Wikipedia's entry

答案 4 :(得分:4)

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

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

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

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

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

答案 5 :(得分:2)

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

interator是一个对象,它有一个.next()函数

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

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

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

答案 6 :(得分: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

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

答案 7 :(得分:0)

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

答案 8 :(得分:0)

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

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