2009-06-20 133 views
28

Iterator和Generator之間有什麼區別?Iterator和Generator之間有什麼區別?

+1

我踢自己輸球的我的副本軌道Griswold關於Icon編程語言的書。據我所知,這就是迭代器和生成器首先顯示爲語言特徵的地方,並且解釋非常好。當然,那是20多年前的事情,我想他們從來沒有用我實際用於製作的任何語言出現。但是現在他們使用Python並加入JavaScript,所以我想我錯了。 – Nosredna 2009-06-20 21:43:04

+1

相似:[Python的生成器和迭代器之間的區別](http://stackoverflow.com/q/2776829/55075),但是對於Python特定的。 – kenorb 2015-09-04 10:32:14

回答

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

生成器是一個迭代器的實現。它通常是一個例程,它爲調用者產生多個值,而不僅僅是一個值。

在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一次遍歷集合之一。

A generator生成一個序列,一次一個項目。

你可能例如,遍歷一個生成的結果...

0

通常迭代器行走在現有的序列(如數組或列表)和發電機計算在每次請求新的價值。

+0

這是不對的。可以使(無發生器的)迭代器例如提供每個自然數的平方。沒有現有的數組或列表對象支持。 – 2009-06-20 21:27:27

0

迭代器通常用於在項目集合中移動。通常使用MoveNext()和Current()方法。 MoveNext()會將指針移到下一個集合項目(如果可能的話),並根據成功返回true/false。 Current()將提供實際值。

生成器是迭代器的實現,但不是指向預先存在的集合,而是在每個MoveNext()調用上創建新項目。

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 

如果你運行這個你可以看到,他們正在計算打印的因素。我們不需要實際保留記憶中所有因素的完整列表。

4

Generator是一個特殊的函數,可以像Iterator一樣工作,每次調用時都會返回一個值。因爲它是一個功能,它可以按需計算每個值。而且由於它很特殊,它可以記住上次調用它的狀態,所以生成的代碼看起來很簡單。

例如,該發電機在Python會產生整數

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

在這個例子中最重要的事情是yield n語句序列。該函數將返回該值,並在下次調用該值時,該值將從該點繼續。

此連結髮電機在Python更詳細的解釋: link text

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); 
     } 
    } 
} 
相關問題