【问题标题】:What is the difference between an Iterator and a Generator?迭代器和生成器有什么区别?
【发布时间】:2010-11-04 14:04:44
【问题描述】:

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

【问题讨论】:

  • 我很自责,因为我忘记了我的 Griswold 关于 Icon 编程语言的书的副本。据我所知,这就是迭代器和生成器首次作为语言特性出现的地方,并且解释得很好。当然,那是 20 多年前的事了,我认为它们永远不会以我在生产中实际使用的任何语言出现。但现在他们使用 Python 并使用 JavaScript,所以我想我错了。
  • 类似:Difference between Python's Generators and Iterators,但特定于 Python。

标签: iterator generator


【解决方案1】:

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

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

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

    在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

    【讨论】:

      【解决方案3】:

      iterator 一次遍历一个集合。

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

      例如,您可能会遍历生成器的结果...

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • 这是不对的。可以制作(没有生成器)一个迭代器,例如提供每个自然数的平方。没有现有的数组或列表对象支持它。
        • 如果你称之为迭代器,那么迭代器和生成器有什么区别?
        • 区别基本上就是unknown(google)说的。 “生成器是与函数绑定的迭代器”。当然,“函数”实际上是一个看起来像函数的状态机。我在答案中提供了一个示例。
        【解决方案5】:

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

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

        【讨论】:

          【解决方案6】:

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

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

          例如,您可以有一个生成器,它可以输出从 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】:

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

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

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

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

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

          【讨论】:

            【解决方案8】:

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

            【讨论】:

              【解决方案9】:

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

              interator 是一个具有 .next() 函数的对象

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

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

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

              【讨论】:

                猜你喜欢
                • 2019-10-25
                • 2021-04-26
                • 2014-12-05
                • 1970-01-01
                • 2012-06-14
                • 2011-07-17
                • 2012-02-10
                • 2013-06-17
                • 2011-08-26
                相关资源
                最近更新 更多