> For the complete documentation index, see [llms.txt](https://kaze.gitbook.io/qa-theory/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kaze.gitbook.io/qa-theory/osnovy-programmirovaniya-na-python/chto-takoe-generator-raznica-mezhdu-generatorami-i-iteratorami.md).

# Что такое генератор? Разница между генераторами и итераторами?

### **1. Итератор**

* Итератор — это объект, который **позволяет проходить по последовательности** (список, строка, кортеж) **один элемент за раз**.
* Итератор реализует методы:
  * `__iter__()` — возвращает сам объект итератора
  * `__next__()` — возвращает следующий элемент, при достижении конца выдаёт `StopIteration`

#### **Пример итератора**

```python
lst = [1, 2, 3]
it = iter(lst)

print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3
# print(next(it))  # StopIteration
```

***

### **2. Генератор**

* Генератор — это **специальный итератор**, который **создаёт элементы "на лету"** при каждой итерации.
* Экономит память, особенно для больших последовательностей.
* Создаётся с помощью:
  1. **Функций с `yield`**
  2. **Генераторных выражений** (`(...)` вместо `[...]`)

#### **2.1 Функция-генератор**

```python
def my_gen(n):
    for i in range(n):
        yield i  # возвращает по одному элементу за раз

gen = my_gen(5)
for val in gen:
    print(val)
```

**Вывод:**

```
0
1
2
3
4
```

#### **2.2 Генераторное выражение**

```python
gen_exp = (x**2 for x in range(5))
print(next(gen_exp))  # 0
print(next(gen_exp))  # 1
```

***

### **3. Разница между генератором и обычным итератором**

| Характеристика       | Итератор                    | Генератор                                      |
| -------------------- | --------------------------- | ---------------------------------------------- |
| Создание             | Через `iter()`              | Функция с `yield` или `(x for x in ...)`       |
| Память               | Элементы хранятся полностью | Элементы создаются по мере запроса             |
| Ключевой метод       | `__next__()`                | `__next__()` (реализован автоматически)        |
| Использование        | Любая последовательность    | Большие последовательности, ленивые вычисления |
| Можно ли пересоздать | Да (создать новый итератор) | Нет, генератор один раз исчерпывается          |

***

### **4. Применение в автотестах**

* **Обработка больших логов или API-данных** без загрузки всего в память.
* **Генерация тестовых данных** на лету:

```python
def test_data(n):
    for i in range(n):
        yield {"username": f"user{i}", "password": "123"}
```

* Используется в **pytest с `@pytest.mark.parametrize`**, когда много комбинаций данных.

***

💡 **Вывод:**

* Генератор = ленивый итератор, экономит память.
* Итератор = объект последовательности, по которому можно пройтись с `next()`.

***

<details>

<summary>Отличия генераторов от генераторных выражений</summary>

В Python есть **два похожих, но разных механизма**:

* **Генераторы** (generator functions) — это функции с `yield`, которые возвращают итератор.
* **Генераторные выражения** (generator expressions) — это компактный синтаксис, похожий на list comprehension, но в круглых скобках.

***

### 1. Генераторы (generator functions)

**Как создаются:**\
Используем `def` и `yield` вместо `return`.

```python
def my_gen():
    yield 1
    yield 2
    yield 3

g = my_gen()
print(next(g))  # 1
print(next(g))  # 2
print(next(g))  # 3
```

📌 **Особенности:**

* `yield` приостанавливает выполнение функции и возвращает значение, но сохраняет состояние (переменные, позицию).
* Можно содержать сложную логику, условия, вложенные циклы.
* Можно использовать в нескольких местах `yield`, в отличие от return, который завершает выполнение.

***

### 2. Генераторные выражения (generator expressions)

**Как создаются:**\
Похожи на list comprehension, но с `()` вместо `[]`.

```python
g = (x**2 for x in range(5))

print(next(g))  # 0
print(next(g))  # 1
print(next(g))  # 4
```

📌 **Особенности:**

* Это короткий синтаксис, когда логика простая.
* Используются чаще для "одноразового" создания потока данных.
* Нельзя написать сложный многострочный код (только одно выражение).

***

### 3. Отличия в таблице

| Критерий             | Генераторы (yield)                      | Генераторные выражения                    |
| -------------------- | --------------------------------------- | ----------------------------------------- |
| **Создание**         | Через `def` и `yield`                   | Через круглые скобки `()`                 |
| **Сложность логики** | Можно писать сложные алгоритмы, условия | Только одно выражение                     |
| **Читаемость**       | Более многословны                       | Короткие и компактные                     |
| **Многострочность**  | Да                                      | Нет                                       |
| **Где использовать** | Когда логика сложная, есть много шагов  | Когда нужно просто и быстро создать поток |
| **Пример**           | `def my_gen(): yield x`                 | `(x for x in range(10))`                  |

***

### 4. Общие черты

* Оба **ленивые** — не создают весь список сразу, а выдают элементы по запросу.
* Оба возвращают **итератор**.
* Можно использовать в `for`, `sum`, `max`, `list()` и т. п.

***

### 5. Когда что использовать

* **Генератор (yield)** — если нужно многострочное вычисление, сложные условия, несколько точек `yield`.
* **Генераторное выражение** — если вычисление короткое и можно записать в одну строчку

</details>
