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

StackOverflow https://stackoverflow.com/questions/1022564

  •  06-07-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

Итератор, как правило, имеет метод 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

Другие советы

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

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

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

Здесь слишком много 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);
        }
    }
}

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

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

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

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

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

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

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

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

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

Интератор - это объект с функцией .next ()

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

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

См. MDN по этому адресу: https: //developer.mozilla .org / EN-US / Docs / Web / JavaScript / Руководство / Iterators_and_Generators

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top