Разница между генераторами и итераторами Python

Я использовал шаблон раньше, т. е. web.dev.config, web.prod.config и т. д., но теперь предпочитаю метод «переопределить файл». Файл web.config содержит большинство параметров, но внешний файл содержит значения, специфичные для среды, такие как соединения db. Хорошее объяснение в блоге Paul Wilson .

Я думаю, что это уменьшает количество дублирования между конфигурационными файлами, которые могут вызвать боль при добавлении новых значений / атрибутов.

464
задан Aaron Hall 5 February 2015 в 20:14
поделиться

3 ответа

Функция генератора, объект генератора, генератор:

Функция генератора похожа на обычную функцию в Python, но содержит одну или более yield заявлений. Функции генератора - отличный инструмент для создания объектов Iterator как можно проще. Объект Iterator , возвращаемый функцией генератора, также называется Generator object или Generator .

В этом примере я создал функцию Generator, которая возвращает объект Generator <generator object fib at 0x01342480>. Как и другие итераторы, объекты Generator могут использоваться в цикле for или со встроенной функцией next(), которая возвращает следующее значение из генератора.

def fib(max):
    a, b = 0, 1
    for i in range(max):
        yield a
        a, b = b, a + b
print(fib(10))             #<generator object fib at 0x01342480>

for i in fib(10):
    print(i)               # 0 1 1 2 3 5 8 13 21 34


print(next(myfib))         #0
print(next(myfib))         #1
print(next(myfib))         #1
print(next(myfib))         #2

Таким образом, функция генератора - это самый простой способ создать объект Iterator.

Итератор :

Каждый объект-генератор является итератором , но не наоборот. Пользовательский объект итератора может быть создан, если его класс реализует метод __iter__ и __next__ (также называемый протоколом итератора).

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

class Fib:
    def __init__(self,max):
        self.current=0
        self.next=1
        self.max=max
        self.count=0

    def __iter__(self):
        return self

    def __next__(self):
        if self.count>self.max:
            raise StopIteration
        else:
            self.current,self.next=self.next,(self.current+self.next)
            self.count+=1
            return self.next-self.current

    def __str__(self):
        return "Generator object"

itobj=Fib(4)
print(itobj)               #Generator object

for i in Fib(4):  
    print(i)               #0 1 1 2

print(next(itobj))         #0
print(next(itobj))         #1
print(next(itobj))         #1
6
ответ дан N Randhawa 5 February 2015 в 20:14
поделиться

Я пишу специально для новичков Python очень простым способом, хотя в глубине души Python делает столько вещей.

Let’s запускаются с очень простого:

Рассматривают список,

l = [1,2,3]

, Let’s пишут эквивалентную функцию:

def f():
    return [1,2,3]

o/p print(l): [1,2,3] & o/p print(f()) : [1,2,3]

Let’s входят в список l повторяемый: В Python список всегда повторяем, который означает, что можно применить итератор каждый раз, когда Вы хотите.

Let’s применяют итератор на список:

iter_l = iter(l) # iterator applied explicitly

Let’s делают функцию повторяемой, т.е. пишут эквивалентную функцию генератора. В Python, как только Вы представляете ключевое слово yield; это становится функцией генератора, и итератор будет применен неявно.

Примечание: Каждый генератор всегда повторяем с неявным примененным итератором, и здесь неявный итератор является затруднением , Таким образом, функция генератора будет:

def f():
  yield 1 
  yield 2
  yield 3

iter_f = f() # which is iter(f) as iterator is already applied implicitly

Поэтому, если Вы наблюдали, как только Вы сделали функцию f генератором, это уже - проход (f)

Теперь,

, л является списком после применения метода итератора "проход", которым это становится, проход (l)

, f уже является проходом (f) после применения метода итератора "проход", которым это становится, проход (проход (f)), который является снова проходом (f)

, Это, любезно с вашей стороны бросают интервал к интервалу (x), который уже является интервалом, и это останется международным (x).

, Например, o/p:

print(type(iter(iter(l))))

<class 'list_iterator'>

, Никогда не забывают, что это - Python и не C или C++

Следовательно, заключение из вышеупомянутого объяснения:

список l ~ = проход (l)

генератор функционируют f == проход (f)

0
ответ дан 22 November 2019 в 22:47
поделиться

итератор - это более общее понятие: любой объект, класс которого имеет метод next (__next__ в Python 3) и метод __iter__, который делает return self.

Каждый генератор является итератором, но не наоборот. Генератор строится путем вызова функции, которая имеет одно или несколько выражений yield (yield statements, в Python 2.5 и более ранних версиях), и является объектом, удовлетворяющим определению итератора из предыдущего параграфа.

Вы можете захотеть использовать пользовательский итератор, а не генератор, если вам нужен класс с несколько сложным поведением, поддерживающим состояние, или вы хотите раскрыть другие методы, кроме next__iter__ и __init__). Чаще всего достаточно генератора (иногда, для достаточно простых нужд, генератора expression), и это проще в коде, потому что поддержание состояния (в разумных пределах) в основном "делается за вас" приостановкой и возобновлением фрейма.

Например, генератор типа:

def squares(start, stop):
    for i in range(start, stop):
        yield i * i

generator = squares(a, b)

или эквивалентное выражение генератора (genexp)

generator = (i*i for i in range(a, b))

потребует больше кода для создания пользовательского итератора:

class Squares(object):
    def __init__(self, start, stop):
       self.start = start
       self.stop = stop
    def __iter__(self): return self
    def next(self): # __next__ in Python 3
       if self.start >= self.stop:
           raise StopIteration
       current = self.start * self.start
       self.start += 1
       return current

iterator = Squares(a, b)

Но, конечно, с классом Squares вы можете легко предложить дополнительные методы, т.е.

    def current(self):
       return self.start

если у вас есть реальная необходимость в такой дополнительной функциональности в вашем приложении.

493
ответ дан 22 November 2019 в 22:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: