迭代器和生成器之间有什么区别?
答案 0 :(得分:37)
答案 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);
}
}
}
答案 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()调用上创建新项目。