Как ни странно, вопрос о разнице между генераторами и итераторами в Python — довольно частый. В общем‑то эти сущности сильно связаны (любой генератор — это итератор), их довольно часто путают, что иногда приводит к недопониманиям.
Итератор — более общая концепция. Это объект, у которого определены два метода: __next__ и __iter__.
С другой стороны, генератор — это итератор, но не наоборот. Генератор может получаться с использованием yield в теле функции:
def squares(start, stop):
for i in range(start, stop):
yield i * i
generator = squares(a, b)
Либо с использованием так называемых generator expression — например, такого:
generator = (i * i for i in range(a, b))
Если посмотреть dir(generator) и в первом, и во втором случае, то обнаружим, что оба варианта — итераторы (определены функции __next__ и __iter__).
По большому счёту, генераторы — это синтаксический сахар. И без них можно писать такие же эффективные программы, используя только итераторы. Вот только читаемость и простота кода сильно снизятся. Так что, если не нужно от итератора ничего сверх естественного, то стоит подумать над использованием генератора.
В примерах и объяснениях я использовал Python 3. Для второй версии языка есть незначительные отличия.