---
title: Итераторы, генераторы, и декораторы
questionDates:
  q-transfer-0154: '2026-10-01'
  q-transfer-0155: '2026-10-01'
  q-transfer-0156: '2026-10-01'
  q-transfer-0157: '2026-10-01'
  q-transfer-0158: '2026-10-01'
  q-transfer-0159: '2026-10-01'
  q-transfer-0240: '2026-10-01'
seo:
  description: >-
    Тема «Итераторы, генераторы, и декораторы» для собеседования Python
    Developer. Что такое декоратор? Чем отличается декоратор от итератора?
  title: Итераторы, генераторы, и декораторы — Python Developer
---

[Все темы Python Developer](/prep/python-developer)

## <strong>Что такое декоратор?</strong> [#q-14bee738d69b810ca194dbb655da6522]

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

<strong>Пример&#58;</strong>

```python
def my_decorator(func):
    def wrapper():
        print("До вызова функции")
        func()
        print("После вызова функции")
    return wrapper

@my_decorator
def say_hello():
    print("Привет!")

say_hello()
```

Этот код создает декоратор <code>my_decorator</code>, который добавляет вывод сообщений до и после вызова функции <code>say_hello&#40;&#41;</code>. Использование декоратора <code>&#64;my_decorator</code> перед определением функции <code>say_hello&#40;&#41;</code> применяет этот декоратор к функции <code>say_hello&#40;&#41;</code>.

:::note[Ссылки для изучения]

1. [Декоратор в Python](https://habr.com/ru/companies/otus/articles/727590/)
   :::

---

## <strong>Чем отличается декоратор от итератора?</strong> [#q-14bee738d69b8152bfdcdd25c1e655f9]

Декоратор и итератор - это два различных концепта в Python.

#### <strong>Декоратор</strong>&#58;

- Декоратор в Python - это функция, которая позволяет изменять поведение другой функции без изменения ее кода.

- Он принимает функцию в качестве аргумента и возвращает другую функцию.

- Декораторы часто используются для добавления функциональности к существующим функциям.

#### <strong>Итератор</strong>&#58;

- Итератор в Python - это объект, который представляет последовательность элементов.

- Он обеспечивает методы для поочередного доступа к элементам последовательности.

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

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

:::note[Ссылки для изучения]

1. [Декоратор в Python](https://habr.com/ru/companies/otus/articles/727590/)
1. [Итераторы Python: iter, next и StopIteration](https://docs.python.org/ru/3/tutorial/classes.html#iterators)
   :::

---

## <strong>Чем отличаются итераторы от генераторов?</strong> [#q-14bee738d69b81f789ffed2cba589e54]

Итераторы могут быть созданы с использованием классов или функции <code>iter&#40;&#41;</code>, а генераторы создаются с использованием ключевого слова <code>yield</code>. Генераторы являются удобным итераторным подходом для создания последовательностей данных.

:::note[Ссылки для изучения]

1. [Итераторы и генераторы Python: протокол обхода и yield](https://docs.python.org/ru/3/tutorial/classes.html#generators)
2. [Чем генератор отличается от итератора. Y_LAB University, с 6:32](https://www.youtube.com/watch?v=Lnk-Xhje27Q&t=392s)

:::

---

## <strong>Каков синтаксис итератора в Python и для каких целей он используются?</strong> [#q-14bee738d69b813aa818ecdeff5702c5]

Итератор в Python представляет собой объект, который предоставляет методы для поочередного доступа к элементам последовательности. Синтаксис итератора в Python включает использование функций <code>iter&#40;&#41;</code> и <code>next&#40;&#41;</code>. Функция <code>iter&#40;&#41;</code> принимает объект и возвращает его итератор, а функция <code>next&#40;&#41;</code> используется для получения следующего элемента из итератора.

Метод <code>\_\_iter\_\_&#40;&#41;</code> в классе используется для создания итератора, который возвращает себя. Метод <code>\_\_next\_\_&#40;&#41;</code> возвращает следующий элемент последовательности и вызывается функцией <code>next&#40;&#41;</code> для доступа к последующим элементам.

<strong>Синтаксис&#58;</strong>

```python
# Создание итератора
my_iter = iter(iterable)

# Получение следующего элемента
next_element = next(my_iter)
```

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

:::note[Ссылки для изучения]

1. [Итераторы Python: iter, next и класс Reverse](https://docs.python.org/ru/3/tutorial/classes.html#iterators)
2. [Протокол итератора в Python. Y_LAB University, с 1:12](https://www.youtube.com/watch?v=Lnk-Xhje27Q&t=72s)

:::

---

## <strong>Каков синтаксис генератора в Python и для каких целей он используются?</strong> [#q-14bee738d69b816a8369dfd921d757a5]

Генератор в Python - это специальный тип итератора, который создается с использованием ключевого слова <code>yield</code>. Он используется для генерации последовательности значений без необходимости загрузки их всех в память одновременно. Генераторы удобны для создания итераторов в функциональном стиле с минимальным объемом кода.

<strong>Синтаксис&#58;</strong>

```python
def my_generator():
    yield value
```

Генератор определяется с использованием ключевого слова <code>def</code>, а затем вместо оператора <code>return</code> используется оператор <code>yield</code>, который возвращает значение и приостанавливает выполнение функции до следующего вызова.

:::note[Ссылки для изучения]

1. [Генераторы Python: yield и приостановка выполнения функции](https://docs.python.org/ru/3/tutorial/classes.html#generators)
2. [Генераторы в Python. Y_LAB University, с 6:32](https://www.youtube.com/watch?v=Lnk-Xhje27Q&t=392s)

:::

---

## <strong>Приведите несколько примеров декораторов в Python.</strong> [#q-14bee738d69b812ba702e296a6de48f5]

<strong>Вот несколько примеров декораторов в Python&#58;</strong>

<strong>Декоратор для замера времени выполнения функции&#58;</strong>

```python
import time

def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Function {func.__name__} executed in {end_time - start_time} seconds")
        return result
    return wrapper

@timer
def example_function():
    time.sleep(2)
    print("Function executed")

example_function()
```

<strong>Декоратор для проверки аргументов функции&#58;</strong>

```python
def validate_input(func):
    def wrapper(*args, **kwargs):
        for arg in args:
            if not isinstance(arg, int):
                raise TypeError("Function arguments must be integers")
        return func(*args, **kwargs)
    return wrapper

@validate_input
def add(x, y):
    return x + y

print(add(3, 5))  # Вывод: 8
```

<strong>Декоратор для кэширования результатов функции&#58;</strong>

```python
def memoize(func):
    cache = {}

    def wrapper(*args):
        if args not in cache:
            cache[args] = func(*args)
        return cache[args]

    return wrapper

@memoize
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(10))  # Вывод: 55
```

:::note[Ссылки для изучения]

1. [Декоратор в Python](https://habr.com/ru/companies/otus/articles/727590/)
   :::

---

## <strong>Приведите несколько примеров генераторов, итераторов в Python.</strong> [#q-14bee738d69b8100b771f5d90d5571e7]

<strong>Вот несколько примеров генераторов и итераторов в Python&#58;</strong>

<strong>Генератор для генерации последовательности чисел Фибоначчи&#58;</strong>

```python
def fibonacci_generator():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fib = fibonacci_generator()
for _ in range(10):
    print(next(fib))  # Вывод: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
```

<strong>
  Генератор для генерации бесконечной последовательности случайных чисел&#58;
</strong>

```python
import random

def random_number_generator():
    while True:
        yield random.randint(1, 100)

rand_gen = random_number_generator()
for _ in range(10):
    print(next(rand_gen))  # Вывод: случайные числа от 1 до 100
```

<strong>Итератор для итерации по строке в обратном порядке&#58;</strong>

```python
class ReverseIterator:
    def __init__(self, data):
        self.data = data
        self.index = len(data)

    def __iter__(self):
        return self

    def __next__(self):
        if self.index == 0:
            raise StopIteration
        self.index -= 1
        return self.data[self.index]

rev_iter = ReverseIterator("hello")
for char in rev_iter:
    print(char)  # Вывод: o, l, l, e, h
```

<strong>Генератор для чтения файла построчно&#58;</strong>

```python
def read_file(filename):
    with open(filename, 'r') as file:
        for line in file:
            yield line.strip()

file_gen = read_file("example.txt")
for line in file_gen:
    print(line)
```

:::note[Ссылки для изучения]

1. [Генератор в Python](https://skillbox.ru/media/code/generatory_python_chto_eto_takoe_i_zachem_oni_nuzhny/)
1. [Пример собственного итератора Reverse на Python](https://docs.python.org/ru/3/tutorial/classes.html#iterators)
1. [Примеры и протокол итерации. Y_LAB University, с 1:12](https://www.youtube.com/watch?v=Lnk-Xhje27Q&t=72s)

:::

---

## Чем итерируемый объект отличается от итератора? [#q-transfer-0154]

Итерируемый объект умеет вернуть итератор через `iter()`, обычно посредством `__iter__`. Итератор дополнительно хранит позицию и выдает элементы через `__next__`, завершаясь `StopIteration`; его `iter()` обычно возвращает его самого. Коллекция может создавать новый итератор для каждого прохода, а генератор является одноразовым итератором: после исчерпания повторный цикл ничего не получит. При выборе учитывают одноразовость обхода, момент возникновения ошибки и срок жизни ресурсов, удерживаемых ленивым вычислением.

:::note[Ссылки для изучения]

1. [Контейнер, iter и next: протокол итератора и StopIteration — Python](https://docs.python.org/ru/3/tutorial/classes.html#iterators)
2. [Итерируемый объект и итератор. Y_LAB University, с 0:33](https://www.youtube.com/watch?v=Lnk-Xhje27Q&t=33s)

:::

---

## Как безопасно работать с бесконечным итератором? [#q-transfer-0155]

Бесконечную последовательность делают генератором или через `itertools.count`, чтобы значения вычислялись по одному. Потребитель обязан задать границу: условие `break`, таймаут, лимит событий либо `itertools.islice`. Нельзя без ограничения передавать такой итератор в `list`, `sum`, сортировку и другие операции, ожидающие конец. Освобождение внешнего ресурса помещают в `finally` и при необходимости явно закрывают генератор. При выборе учитывают одноразовость обхода, момент возникновения ошибки и срок жизни ресурсов, удерживаемых ленивым вычислением.

:::note[Ссылки для изучения]

1. [Бесконечный count: ограничение обхода через break, next и islice — OTUS](https://habr.com/ru/companies/otus/articles/958068/)
   :::

---

## Когда генератор лучше списка, а когда хуже? [#q-transfer-0156]

Генератор выгоден для большого или потокового набора: он вычисляет элементы лениво и не хранит всю последовательность. Цена этого решения: нет произвольной индексации, длины, изменения элементов и бесплатного повторного прохода; ошибка может возникнуть только во время потребления. Список лучше для небольшого результата, который нужно многократно обходить, сортировать или индексировать. Генератор также может удерживать открытый ресурс до исчерпания или закрытия. При выборе учитывают одноразовость обхода, момент возникновения ошибки и срок жизни ресурсов, удерживаемых ленивым вычислением.

:::note[Ссылки для изучения]

1. [Генераторы и экономия памяти по сравнению со списковыми включениями — Python](https://docs.python.org/ru/3/tutorial/classes.html#generator-expressions)
2. [Генератор и расход памяти. Y_LAB University, с 7:53](https://www.youtube.com/watch?v=Lnk-Xhje27Q&t=473s)

:::

---

## Зачем собственному декоратору functools.wraps? [#q-transfer-0157]

`functools.wraps(original)` копирует в функцию-обертку имя, документацию, аннотации и другие метаданные, а также устанавливает `__wrapped__`. Это делает трассировки, документацию, `inspect.signature` и инструменты внедрения зависимостей понятнее. Декоратор продолжает менять поведение функции, а `wraps` не проверяет совместимость сигнатуры. Его ставят на внутреннюю функцию каждого обычного декоратора. Поведение также проверяют через интроспекцию реальной обертки и инструменты фреймворка, которые читают исходную сигнатуру. Это особенно важно для CLI и dependency injection.

:::note[Ссылки для изучения]

1. [functools.wraps: сохранение имени и документации декорированной функции](https://proproprogs.ru/python_base/python3-dekoratory-s-parametrami-sohranenie-svoystv-dekoriruemyh-funkciy)
   :::

---

## Что делает yield from? [#q-transfer-0158]

`yield from iterable` передает наружу все элементы вложенного итерируемого объекта и заменяет ручной цикл `for ...: yield ...`. Если делегирование идет другому генератору, оператор также проксирует `send`, `throw` и `close`, а значение его `return` становится результатом выражения `yield from`. Для обычного списка остается только последовательная выдача элементов, без генераторного диалога. При выборе учитывают одноразовость обхода, момент возникновения ошибки и срок жизни ресурсов, удерживаемых ленивым вычислением.

:::note[Ссылки для изучения]

1. [yield from: делегирование next, send и throw вложенному генератору](https://habr.com/ru/articles/866616/)
   :::

---

## Как generator.send() передает значение внутрь генератора? [#q-transfer-0159]

После остановки на `yield` вызов `send(value)` возобновляет генератор, а переданное значение становится результатом выражения `yield` внутри него. Генератор выполняется до следующего `yield`: это следующее выданное значение возвращается из `send`. До первой остановки нельзя послать ненулевое значение, поэтому начинают с `next(gen)` или `gen.send(None)`. Завершение по `return` проявляется как `StopIteration`. При выборе учитывают одноразовость обхода, момент возникновения ошибки и срок жизни ресурсов, удерживаемых ленивым вычислением.

:::note[Ссылки для изучения]

1. [generator.send: значение внутри yield и продолжение до следующей остановки](https://habr.com/ru/articles/866616/)
   :::

---

## Как устроен декоратор с аргументами? [#q-transfer-0240]

Декоратор с аргументами состоит из трех вызовов: фабрика принимает настройки и возвращает декоратор; декоратор принимает исходную функцию и возвращает обертку; обертка вызывается вместо функции. Настройки сохраняются в замыкании. На обертку ставят `functools.wraps`. Нужно различать время импорта, когда выполняются первые два уровня, и время обычного вызова, когда выполняется обертка. При выборе учитывают одноразовость обхода, момент возникновения ошибки и срок жизни ресурсов, удерживаемых ленивым вычислением.

:::note[Ссылки для изучения]

1. [Декоратор с аргументами: фабрика, декоратор и обёртка — selfedu](https://proproprogs.ru/python_base/python3-dekoratory-s-parametrami-sohranenie-svoystv-dekoriruemyh-funkciy)
   :::
