2009-06-20 10 views
28

イテレータとジェネレータの違いは何ですか?イテレータとジェネレータの違いは何ですか?

+1

私は私のコピーのトラックを失うために自分を蹴っています:

はJavaScriptで、発電機の機能は、特別な構文関数*(){}とyieldキーワードこの上

参照MDNのために使用する必要がありますIconプログラミング言語に関するGriswoldの本の私が知る限り、それはイテレータとジェネレータが言語機能として最初に出てきたもので、その説明は素晴らしいものでした。もちろん、これは20年以上前のことであり、私は彼らが実際にプロダクションで使用する言語では決して表示されないだろうと考えました。しかし、今はPythonでJavaScriptを使用しているので、私は間違っていたと思います。 – Nosredna

+1

類似:[Pythonのジェネレータとイテレータの違い](http://stackoverflow.com/q/2776829/55075)。 – kenorb

答えて

34

ジェネレータはイテレータですが、すべてのイテレータがジェネレータであるとは限りません。

イテレータは、通常、ストリームから次の要素を取得するために次のメソッドを持つものです。ジェネレータは、関数に結び付けられたイテレータです。例えば

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 
5

ジェネレータは、イテレータの実装です。これは通常、1つではなく複数の値を呼び出し元に渡すルーチンです。 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

iterator

は、一度にコレクション1を横断します。

generatorは、一度に1つの項目を生成します。

あなたは、たとえば、発電機の結果を反復処理するかもしれません...通常

0

イテレータは、(配列やリストなど)既存のシーケンス上を歩くと発電機はすべての要求に応じて新しい値を計算します。

+0

これは正しくありません。例えば、自然数の2乗を提供するイテレータを(ジェネレータなしで)作成することは可能です。既存の配列オブジェクトまたはリストオブジェクトは存在しません。 –

+0

それをイテレータと呼ぶと、イテレータとジェネレータの違いは何ですか? –

+0

違いは基本的には未知(google)だと言われています。 "ジェネレータは、関数に結び付けられたイテレータです"。もちろん、「関数」は実際には関数のように見える状態マシンです。私は答えの例を提供しました。 –

0

イテレータは、アイテムのコレクションを移動するために一般的に使用されます。 MoveNext()およびCurrent()メソッドを持つことがよくあります。 MoveNext()は、ポインタを次のコレクション項目に移動し(可能な場合)、成功に基づいてtrue/falseを返します。 Current()は実際の値を提供します。

ジェネレータはイテレータの実装ですが、既存のコレクションを指す代わりに、各MoveNext()呼び出しで新しいアイテムを作成します。

1

イテレータは、配列、リンクリスト、ツリー、ハッシュマップなど、コレクション内のオブジェクトを反復するために使用されます。あなたにはたくさんのオブジェクトがあり、それぞれのオブジェクトで何かしたいと思っています。

ジェネレータは、オブジェクトをいくつかの有限のコレクションから返すだけではありません。代わりに、それらをオンザフライで生成します。 を反復処理している間に、というコレクション上の反復子として概念化することができ、有限のサイズではない可能性があります。

たとえば、2から無限大の素数を吐き出すジェネレータを使用できます。 「すべての素数」のコレクションを持つことができ、イテレータで繰り返し処理する方法はありません。あなたは発電機が必要です。

または、整数を取り、その数値の要素を一度に生成するジェネレータを使用できます。前もってすべての要因にメモリを割り当てることなく、要因を1つずつ調べることができるので、ジェネレータがここで役立ちます。また、リスト全体を生成する必要はなく、生成されたときにそれらを使用することができます。これは、あなたが好むよりも遅い可能性があります。ここではPythonで、このような発電機の例です:

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

for n in factors(1234567890): 
    print n 

あなたがこれを実行する場合は、それらが計算されているとして印刷要因を見ることができます。私たちは実際にすべての要因のリスト全体をメモリに保持する必要はありません。

+1

もう一度、これは間違っています。イテレータは、「本当の」バッキングコレクション(配列、リンクリストなど)を持つ必要はありません。 –

4

Generatorは、呼び出されるたびに値を返すIteratorとして動作できる特殊な関数です。それは関数なので、必要に応じて各値を計算できます。特殊なので、最後に呼び出されたときの状態を覚えているので、結果のコードはかなりシンプルに見えます。例えば

、Pythonでこの発電機は、この例で重要なことはyield n文です整数

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

のシーケンスを生成します。この関数は値を返し、次回呼び出されるとその点から処理を続けます。

このリンクは、Pythonでジェネレータの長い説明があります。 link text

6

ありすぎて、Pythonはここだ、と発電機を言って、あまりにも多くの人々が無限のイテレータを実装するための唯一の方法です。ここでは、C#で実装された例(すべての自然数の2乗)を示します。 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); 
     } 
    } 
} 
関連する問題