Question

Quelle est la différence entre un itérateur et un générateur?

Était-ce utile?

La solution

Les générateurs sont des itérateurs, mais tous les itérateurs ne sont pas des générateurs.

Un itérateur est généralement quelque chose qui a une méthode next pour obtenir le prochain élément d'un flux. Un générateur est un itérateur lié à une fonction.

Par exemple un générateur en python:

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

Cela présente l'avantage que vous n'avez pas besoin de stocker en mémoire des nombres infinis pour les parcourir.

Vous utiliseriez cela comme n'importe quel itérateur:

for i in genCountingNumbers():
  print i
  if i > 20: break  # Avoid infinite loop

Vous pouvez également parcourir un tableau:

for i in ['a', 'b', 'c']:
  print i

Autres conseils

Un itérateur parcourt une collection à la fois.

Un générateur génère une séquence, élément par élément.

Vous pouvez par exemple parcourir le résultat d'un générateur ...

Il y a trop de Python ici et trop de gens qui disent que les générateurs sont le seul moyen de mettre en œuvre un itérateur infini. Voici l'exemple que j'ai mentionné (carrés de tous les nombres naturels) implémenté en C #. ExplicitSquares implémente explicitement un itérateur (appelé IEnumerator en C #). ImplicitSquares utilise un générateur pour faire la même chose. Les deux sont des itérateurs infinis et n'ont pas de collection de sauvegarde. La seule différence est que la machine à états est épelée ou qu’un générateur soit utilisé.

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);
        }
    }
}

Un générateur est une implémentation d'un itérateur. C’est généralement une routine qui donne plusieurs valeurs à son appelant et non une seule.

En 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);
    }
}
}

Voir l'entrée de Wikipedia

Un générateur est une fonction spéciale qui peut se comporter comme un itérateur, renvoyant une valeur à chaque appel. Parce que c'est une fonction, il peut calculer chaque valeur à la demande. Et comme il est spécial, il peut se rappeler son état de la dernière fois où il a été appelé. Le code résultant semble donc assez simple.

Par exemple, ce générateur en python produira une séquence d'entiers

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

L'important dans cet exemple est l'instruction yield n . La fonction renverra la valeur et la prochaine fois qu'elle sera appelée, elle continuera à partir de ce point.

Ce lien contient une explication plus longue des générateurs en python: texte du lien

(de javascript useland, pourtant identique à tous les autres)

Un interator est un objet ayant une fonction .next ()

Un générateur est une fonction qui, une fois appelée, produit un itérateur, c’est une fabrique pour itérateur.

En javascript, la fonction de générateur nécessite une fonction de syntaxe spéciale * () {} ainsi que l'utilisation du mot clé de rendement

.

Voir le MDN à ce sujet: https: //developer.mozilla .org / en-US / docs / Web / JavaScript / Guide / Iterators_and_Generators

Un itérateur est utilisé pour parcourir les objets d'une collection, qu'il s'agisse d'un tableau, d'une liste liée, d'un arbre, d'une carte de hachage, etc. Vous avez un tas d'objets et vous voulez faire quelque chose avec chacun d'eux.

Un générateur ne renvoie pas seulement les éléments d’une collection finie d’objets. Au lieu de cela, il les génère à la volée. Vous pouvez le conceptualiser comme un itérateur sur une collection créée pendant que vous le parcourez et que la taille ne soit pas nécessairement finie.

Par exemple, vous pourriez avoir un générateur qui crache des nombres premiers de 2 à l'infini. Il n’ya aucun moyen d’avoir une collection de " tous les nombres premiers " et itérer dessus avec un itérateur. Vous avez besoin d'un générateur.

Vous pouvez aussi avoir un générateur qui prend un entier et renvoie les facteurs de ce nombre un à la fois. Un générateur vous serait utile ici, car vous pourriez examiner les facteurs un par un sans allouer de mémoire pour tous les facteurs au départ. Cela vous permettrait également de les utiliser au fur et à mesure de leur génération, sans avoir à générer la liste complète à l’avance, ce qui peut être plus lent que vous le souhaitez. Voici un exemple d'un tel générateur en Python:

def factors(n):
    for i in xrange(1, n+1):
        if n % i == 0:
            yield i

for n in factors(1234567890):
    print n

Si vous exécutez ceci, vous pouvez voir les facteurs imprimés tels qu'ils sont calculés. Nous n'avons pas besoin de conserver en mémoire une liste complète de tous les facteurs.

Un itérateur est couramment utilisé pour parcourir une collection d'éléments. Ayant souvent des méthodes MoveNext () et Current (). MoveNext () déplacerait le pointeur sur le prochain élément de la collection (si possible) et renverrait true / false en cas de succès. Current () fournirait la valeur réelle.

Un générateur est une implémentation d'itérateur, mais au lieu de pointer vers une collection préexistante, il crée de nouveaux éléments à chaque appel de MoveNext ().

Généralement, les itérateurs parcourent une séquence existante (telle qu'un tableau ou une liste) et les générateurs calculent une nouvelle valeur à chaque requête.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top