Пояснение по итераторам и генераторам python

Прошу совета/пояснения: Где лучше использовать генератор, а где итератор.

Допустим есть итератор:

class MyIter1:
    def __init__(self, num):
        self.num = num

    def __iter__(self):
        return self

    def __next__(self):
        if self.num > 0:
            self.num -= 1
            return self.num
        raise StopIteration

И цикл for:

for i in MyIter1(10):
    print(i)

В цикле у MyIter1 вызывается метод __next__ и используется значение, которое он вернул.

И есть генератор:

def gen(num):
    for x in range(num):
        if num > 0:
            num -= 1
            yield num

И к нему такой же цикл for:

for i in gen(10):
    print(i)

В цикле у gen вызывается next() и используется значение, которое он вернул.

И вот вопросы:

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

P.S. Я знаком с генераторами и понимаю принцип их работы, что их применяют для потоковой обработки данных, но я не до конца понимаю в чём разница, ведь это можно сделать и итератором, просто вызывая у него __next__() тогда, когда это требуется.


Ответы (1 шт):

Автор решения: SergFSM

Пример использования генератора:

def flatten(sequence):
    for element in sequence:
        if hasattr(element, '__iter__'):
            yield from flatten(element)
        else:
            yield element

print(*flatten([1, [2], [3, [4]]]), sep=' ')
'''
1 2 3 4

А как бы вы реализовали это с помощью итератора?

→ Ссылка