В чем разница между итератором и генератором? - PullRequest
30 голосов
/ 21 июня 2009

В чем разница между итератором и генератором?

Ответы [ 9 ]

37 голосов
/ 21 июня 2009

Итератор перебирает коллекцию по одному за раз.

Генератор генерирует последовательность, по одному элементу за раз.

Вы можете, например, перебрать результат генератора ...

34 голосов
/ 21 июня 2009

Генераторы являются итераторами, но не все итераторы являются генераторами.

Итератор, как правило, имеет метод next для получения следующего элемента из потока. Генератор - это итератор, связанный с функцией.

Например, генератор на 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
6 голосов
/ 21 июня 2009

Здесь слишком много Python, и слишком много людей говорят, что генераторы - это только способ реализации бесконечного итератора. Вот пример, который я упомянул (квадраты всех натуральных чисел), реализованный в C #. ExplicitSquares явно реализует итератор (называемый IEnumerator в C #). 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);
        }
    }
}
5 голосов
/ 21 июня 2009

Генератор - это реализация итератора. Обычно это процедура, которая выдает множеству значений своему вызывающему, а не только одному.

В с #

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

См. Статью в Википедии

4 голосов
/ 21 июня 2009

Генератор - это специальная функция, которая может вести себя как итератор, возвращая значение при каждом ее вызове. Поскольку это функция, она может вычислять каждое значение по требованию. А поскольку он особенный, он может вспомнить свое состояние с момента последнего вызова, поэтому полученный код выглядит довольно просто.

Например, этот генератор в python выдаст последовательность целых чисел

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

Важной вещью в этом примере является оператор yield n. Функция вернет значение и при следующем вызове продолжит работу с этой точки.

Эта ссылка содержит более подробное описание генераторов в python: текст ссылки

2 голосов
/ 21 августа 2016

(из javascript useland, но так же, как и все остальные)

Интератором является объект с функцией .next ()

Генератор - это функция , после вызова создайте итератор, это фабрика для итератора.

В javascript для функции генератора требуется специальная синтаксическая функция * () {} и использование для ключевого слова yield

См. MDN по этому вопросу: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators

1 голос
/ 21 июня 2009

Итератор используется для итерации по объектам в коллекции, будь то массив, связанный список, дерево, хеш-карта, что угодно. У вас есть куча объектов, и вы хотите что-то сделать с каждым из них.

Генератор не просто возвращает элементы из некоторой конечной коллекции объектов. Вместо этого он генерирует их на лету. Вы можете концептуализировать его как итератор для коллекции, которая создается , в то время как вы итерируете ее и, возможно, не имеете конечного размера.

Например, у вас может быть генератор, который выплевывает простые числа от 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

Если вы запустите это, вы увидите напечатанные коэффициенты в том виде, в каком они рассчитаны. Нам не нужно фактически вести полный список всех факторов в памяти.

0 голосов
/ 21 июня 2009

Итератор обычно используется для перемещения по коллекции элементов. Часто с методами MoveNext () и Current (). MoveNext () переместит указатель на следующий элемент коллекции (если это возможно) и вернет true / false в зависимости от успеха. Current () предоставит фактическое значение.

Генератор - это реализация итератора, но вместо указания на уже существующую коллекцию он создает новые элементы при каждом вызове MoveNext ().

0 голосов
/ 21 июня 2009

Обычно итераторы обходят существующую последовательность (например, массив или список), а генераторы вычисляют новое значение при каждом запросе.

...