2009-06-20 12 views
28

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

+1

Je me coups de pied pour perdre la trace de ma copie du livre de Griswold sur le langage de programmation Icon. Autant que je sache, c'est là que les itérateurs et les générateurs se sont présentés pour la première fois en tant qu'éléments du langage, et les explications étaient excellentes. Bien sûr, c'était il y a plus de 20 ans et je me suis dit qu'ils ne se présenteraient jamais dans une langue que j'utiliserais en production. Mais maintenant, ils sont en Python et viennent à JavaScript, donc je suppose que j'avais tort. – Nosredna

+1

Similaire: [Différence entre les générateurs de Python et les itérateurs] (http://stackoverflow.com/q/2776829/55075), mais spécifique à Python. – kenorb

Répondre

34

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

Un itérateur est typiquement quelque chose qui a une méthode suivante pour obtenir l'élément suivant 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 

Ceci a l'avantage que vous n'avez pas besoin de stocker un nombre infini en mémoire pour itérer sur eux.

Vous souhaitez l'utiliser comme vous le feriez pour tout iterator:

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

Vous pouvez également itérer sur un tableau:

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

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 par opposition à un seul.

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

See Wikipedia's entry

37

Un iterator traverse une collection un à la fois. Un generator génère une séquence, un élément à la fois.

Vous pouvez par exemple, itérer sur le résultat d'un générateur ...

0

Habituellement itérateurs marcher sur une séquence existante (par exemple un tableau ou une liste) et générateurs calcule une nouvelle valeur à chaque demande.

+0

Ce n'est pas correct. Il est possible de faire (sans générateur) un Iterator qui fournit par exemple le carré de chaque nombre naturel. Il n'y a aucun objet array ou list supportant cela. –

+0

Si vous appelez cela un itérateur alors quelle est la différence entre un itérateur et un générateur? –

+0

La différence est fondamentalement ce que l'inconnu (google) a dit. Un "générateur est un itérateur lié à une fonction". Bien sûr, la "fonction" est vraiment une machine d'état qui ressemble à une fonction. J'ai fourni un exemple dans une réponse. –

0

Un itérateur est couramment utilisé pour se déplacer dans une collection d'éléments. Ayant souvent des méthodes MoveNext() et Current(). MoveNext() déplace le pointeur vers l'élément de collection suivant (si possible) et renvoie 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 MoveNext().

1

Un itérateur est utilisé pour itérer sur les objets d'une collection, qu'il s'agisse d'un tableau, d'une liste chaînée, d'un arbre, d'une table 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 pourriez le conceptualiser comme un itérateur sur une collection qui est créée pendant que vous itérez dessus et peut ne pas avoir la taille finie. Par exemple, vous pouvez avoir un générateur qui crache les nombres premiers de 2 à l'infini. Il n'y a aucun moyen que vous puissiez avoir une collection de "tous les nombres premiers" et parcourir avec un itérateur. Vous avez besoin d'un générateur.

Ou vous pourriez avoir un générateur qui prend un nombre entier et donne les facteurs de ce nombre un à la fois. Un générateur vous serait bénéfique ici car vous pourriez examiner les facteurs un par un sans allouer la mémoire pour tous les facteurs à l'avance. Cela vous permettrait également de les utiliser au fur et à mesure de leur génération plutôt que de devoir générer toute la liste à l'avance, ce qui pourrait ê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 cela, vous pouvez voir les facteurs imprimés comme ils sont calculés. Nous n'avons pas besoin de maintenir une liste complète de tous les facteurs en mémoire.

+1

Encore une fois, c'est faux. Les itérateurs n'ont pas besoin d'avoir une "vraie" collection de sauvegarde (tableau, liste chaînée, peu importe). –

4

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

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

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

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

Ce lien a une explication plus des générateurs en python: link text

6

Il y a trop de Python ici, et trop de gens en disant générateurs sont les que façon de mettre en œuvre un iterator 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 aucune collection de backing. La seule différence est de savoir si la machine d'état est épelée ou si un générateur est 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); 
     } 
    } 
} 
2

(useland de javascript, mais même que tous les autres)

Un interator est un objet qui a une fonction .next()

Un générateur est une fonction , une fois invoqué, produire un itérateur, c'est une usine pour itérateur.

En javascript, la fonction générateur nécessitent une fonction de syntaxe spéciale *() {} et l'utilisation pour le mot-clé yield

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