迭代器和生成器有什么区别?
9 回答
生成器是迭代器,但并非所有迭代器都是生成器。
迭代器通常是具有从流中获取下一个元素的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
这里有太多的 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);
}
}
}
生成器是迭代器的实现。它通常是一个例程,它为调用者产生多个值,而不是一个。
在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);
}
}
}
生成器是一个特殊的函数,它可以作为一个迭代器,每次调用它都会返回一个值。因为它是一个函数,它可以按需计算每个值。而且因为它很特殊,它可以记住上次调用时的状态,所以生成的代码看起来很简单。
例如,python中的这个生成器将产生一个整数序列
def integers():
int n = 0
while True:
yield n
n += 1
这个例子中最重要的是yield n
语句。该函数将返回该值,并且下次调用它时,它将从该点继续。
这个链接对python中的生成器有更长的解释: link text
(来自javascript useland,但与所有其他人一样)
插入器是具有 .next() 函数的对象
生成器是一个函数,一旦被调用,就会产生一个迭代器,它是一个迭代器的工厂。
在 javascript 中,生成器函数需要特殊的语法函数 *(){} 并使用 yield 关键字
请参阅 MDN:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators
通常迭代器遍历现有序列(例如数组或列表),生成器在每次请求时计算一个新值。
迭代器用于迭代集合中的对象,可以是数组、链表、树、哈希映射等。你有一堆对象,你想对它们中的每一个做一些事情。
生成器不只是从一些有限的对象集合中返回项目。相反,它会即时生成它们。您可以将其概念化为对在迭代时创建的集合的迭代器,并且可能没有有限的大小。
例如,您可以有一个生成器,它可以输出从 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
如果你运行它,你可以看到计算出来的因子。我们实际上不需要在内存中维护所有因素的完整列表。
迭代器通常用于在项目集合中移动。通常有 MoveNext() 和 Current() 方法。MoveNext() 会将指针移动到下一个集合项(如果可能)并根据成功返回真/假。Current() 将提供实际值。
生成器是迭代器的实现,但它不是指向预先存在的集合,而是在每次 MoveNext() 调用时创建新项目。