Qual é a diferença entre um Iterator e um gerador?
Pergunta
Qual é a diferença entre um Iterator e um gerador?
Solução
Os geradores são iteradores, mas nem todos os iteradores são geradores.
Um iterador é tipicamente algo que tem um próximo método para obter o próximo elemento de um córrego. Um gerador é um iterador que está vinculado a uma função.
Por exemplo, um gerador em python:
def genCountingNumbers():
n = 0
while True:
yield n
n = n + 1
Isto tem a vantagem de que você não precisa armazenar números infinitos na memória para iterar sobre eles.
Você usaria isso como faria com qualquer iterator:
for i in genCountingNumbers():
print i
if i > 20: break # Avoid infinite loop
Você também poderia iteração sobre um array:
for i in ['a', 'b', 'c']:
print i
Outras dicas
Há muito Python aqui, e muitas pessoas dizendo geradores são o única maneira de implementar um iterador infinito. Aqui está o exemplo que citei (quadrados de todos os números naturais) implementados em C #. ExplicitSquares implementa explicitamente um iterador (chamado IEnumerator em C #). ImplicitSquares usa um gerador para fazer a mesma coisa. Ambos são infinitas iteradores e não têm coleta de apoio. A única diferença é se a máquina de estado está escrito para fora, ou, alternativamente, um gerador é usado.
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);
}
}
}
Um gerador é uma implementação de um iterador. É tipicamente uma rotina que os rendimentos vários valores para seu chamador ao invés de apenas um.
Em 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);
}
}
}
A Generator é uma função especial que pode se comportar como um Iterator, retornando um valor cada vez que ele é chamado. Porque é uma função, ele pode computar cada valor na demanda. E porque ele é especial, ele pode lembrar seu estado a partir da última vez que foi chamado, portanto, o código resultante parece muito simples.
Por exemplo, este gerador em python irá produzir uma sequência de números inteiros
def integers():
int n = 0
while True:
yield n
n += 1
O importante neste exemplo é a declaração yield n
. A função irá retornar o valor, ea próxima vez que for chamado, ele vai continuar a partir desse ponto.
Este link tem uma explicação mais longa de geradores em python: texto do link
(de useland javascript, mas mesmo que todos os outros)
Um interator é uma objeto que tem uma função .next ()
Um gerador é uma função , uma vez invocado, produzir um iterador, é uma fábrica de iterador.
Em javascript, função de gerador requerem uma função sintaxe especial * () {} eo uso para o rendimento palavra-chave
Veja MDN sobre isso: https: //developer.mozilla .org / pt-bR / docs / web / JavaScript / Guia / Iterators_and_Generators
Um iterador é usado para iterar sobre os objetos em uma coleção, seja uma matriz, lista, árvore, mapa de hash, ligada o que quer. Você tem um monte de objetos e você quer fazer alguma coisa com cada um deles.
Um gerador não apenas devolver os itens de algum conjunto finito de objetos. Em vez disso, ele gera-los na mosca. Você poderia conceituá-lo como um iterador sobre uma coleção que é criada enquanto estiver a iteração sobre ele e não pode ter tamanho finito.
Por exemplo, você poderia ter um gerador que cospe números primos de 2 a infinito. Não há nenhuma maneira você poderia ter uma coleção de "todos os números primos" e iterate sobre ele com um iterador. Você precisa de um gerador.
Ou você poderia ter um gerador que leva um inteiro e produz os fatores desse número um de cada vez. Um gerador iria beneficiá-lo aqui como você poderia examinar os fatores um por um, sem alocação de memória para todos os fatores adiantado. Também permitiria que você a usá-los como eles são gerados, em vez de ter que gerar a lista inteira na frente, o que pode ser mais lento do que você gosta. Aqui está um exemplo de como gerador de uma em Python:
def factors(n):
for i in xrange(1, n+1):
if n % i == 0:
yield i
for n in factors(1234567890):
print n
Se você executar isso, você pode ver os fatores impressos como eles são calculados. Nós não precisa realmente manter uma lista inteira de todos os fatores em memória.
Um iterador é comumente usado para percorrer uma coleção de itens. Tendo frequentemente moveNext () e métodos correntes (). MoveNext () iria mudar o ponteiro para o próximo item de coleção (se possível) e retornar true / false com base no sucesso. Atual () iria fornecer o valor real.
Um gerador é uma implementação do iterador, mas em vez de apontar para uma coleção pré-existente, ele cria novos itens em cada chamada MoveNext ().
Normalmente iterators andar sobre uma seqüência existente (como uma matriz ou lista) e geradores de calcular um novo valor sobre cada solicitação.