Статьи

Учебные материалы по языку Python — от основ до продвинутых тем

Итераторы, генераторы и декораторы

Страница 14 из 34 · 2026-10-26 · 2 мин чтения

Итераторы

Объект итерируемый, если у него есть метод __iter__. Итератор дополнительно реализует __next__:

numbers = [1, 2, 3]it = iter(numbers)print(next(it))print(next(it))print(next(it))

Когда элементы кончаются, next вызывает StopIteration — именно так цикл for понимает, что пора остановиться.

Собственный итератор:

class Countdown:    def __init__(self, start):        self.current = start    def __iter__(self):        return self    def __next__(self):        if self.current <= 0:            raise StopIteration        value = self.current        self.current -= 1        return valuefor n in Countdown(3):    print(n)

Генераторы

Функция с yield возвращает генератор — ленивый итератор:

def countdown(start):    while start > 0:        yield start        start -= 1for n in countdown(3):    print(n)

Состояние функции сохраняется между вызовами next. Значения вычисляются по требованию, что позволяет работать с огромными или бесконечными последовательностями:

def naturals():    n = 0    while True:        yield n        n += 1gen = naturals()print(next(gen), next(gen), next(gen))

Генераторные выражения

total = sum(x ** 2 for x in range(1_000_000))

В отличие от списка, список значений в памяти не создаётся.

yield from

def chain(*iterables):    for it in iterables:        yield from itprint(list(chain([1, 2], "ab")))

Модуль itertools

from itertools import count, islice, chain, product, permutations, combinations, groupbyprint(list(islice(count(10), 3)))print(list(chain([1], [2, 3])))print(list(product("ab", repeat=2)))print(list(permutations([1, 2, 3], 2)))print(list(combinations([1, 2, 3], 2)))

Замыкания

def multiplier(factor):    def multiply(x):        return x * factor    return multiplydouble = multiplier(2)print(double(5))

Декораторы

Декоратор — функция, которая принимает функцию и возвращает новую:

import functoolsimport timedef timer(func):    @functools.wraps(func)    def wrapper(*args, **kwargs):        start = time.perf_counter()        result = func(*args, **kwargs)        elapsed = time.perf_counter() - start        print(f"{func.__name__}: {elapsed:.4f} с")        return result    return wrapper@timerdef work(n):    return sum(range(n))work(1_000_000)

Запись @timer эквивалентна work = timer(work). Декоратор functools.wraps сохраняет имя и документацию исходной функции.

Декоратор с параметрами

import functoolsdef repeat(times):    def decorator(func):        @functools.wraps(func)        def wrapper(*args, **kwargs):            result = None            for _ in range(times):                result = func(*args, **kwargs)            return result        return wrapper    return decorator@repeat(3)def hello():    print("hello")hello()

Готовые декораторы

from functools import lru_cache, cache@lru_cache(maxsize=None)def fib(n):    if n < 2:        return n    return fib(n - 1) + fib(n - 2)print(fib(80))

Задания

  1. Напишите генератор чисел Фибоначчи, выдающий значения до заданного предела.
  2. Реализуйте декоратор retry, повторяющий вызов функции при исключении заданное число раз.
  3. Прочитайте большой файл построчно с помощью генератора, отфильтровав строки по условию.