← Назад к вопросам

Можно ли в for передать итератор в Python?

1.3 Junior🔥 171 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Можно ли передать итератор в for цикл в Python?

Да, абсолютно можно. Это один из основных способов использования итераторов. На самом деле, for цикл работает именно с итераторами.

1. Как работает for цикл внутри

Когда ты пишешь for x in iterable, Python делает следующее:

# Это:
for item in iterable:
    print(item)

# Эквивалентно этому:
iterator = iter(iterable)  # Преобразует в итератор
while True:
    try:
        item = next(iterator)  # Вызывает __next__()
        print(item)
    except StopIteration:
        break

2. Прямое использование итератора в for

# Создаём итератор
class CountUp:
    def __init__(self, max):
        self.max = max
        self.current = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current < self.max:
            self.current += 1
            return self.current
        raise StopIteration

# Используем итератор в for цикле
iterator = CountUp(3)
for num in iterator:
    print(num)  # 1, 2, 3

# Или прямо создаём в for
for num in CountUp(3):
    print(num)  # 1, 2, 3

3. Встроенные итераторы

Практически всё, что можно использовать в for, — это итератор:

# Список создаёт итератор
for item in [1, 2, 3]:
    print(item)

# Генератор уже является итератором
def gen():
    yield 1
    yield 2
    yield 3

for item in gen():
    print(item)

# Строка тоже итерируемая
for char in "hello":
    print(char)  # h, e, l, l, o

# Словарь создаёт итератор по ключам
for key in {"a": 1, "b": 2}:
    print(key)  # a, b

# Файловый объект — итератор
with open('file.txt') as f:
    for line in f:
        print(line)

4. Важный момент: истощение итератора

Один и тот же итератор нельзя использовать дважды:

# Пример итератора
iterator = iter([1, 2, 3])

# Первый for
for item in iterator:
    print(item)  # 1, 2, 3

# Второй for — НЕ СРАБОТАЕТ!
for item in iterator:
    print(item)  # Ничего не выведет

# Итератор уже истощен
print(next(iterator, "End"))  # End

5. Разница между итератором и итерируемым

Итерируемое (iterable) — может создать итератор:

list_obj = [1, 2, 3]  # Итерируемое
print(hasattr(list_obj, '__iter__'))  # True

iterator = iter(list_obj)  # Создаём итератор
print(type(iterator))  # <class 'list_iterator'>

Итератор — имеет __next__ и может быть использован в for:

iterator = iter([1, 2, 3])  # Это итератор
for item in iterator:
    print(item)  # Работает!

6. Практические примеры

Пример 1: Итератор по файлам в директории

import os
from pathlib import Path

class DirectoryIterator:
    def __init__(self, path):
        self.path = Path(path)
        self.files = None
        self.index = 0
    
    def __iter__(self):
        self.files = list(self.path.glob('*'))
        self.index = 0
        return self
    
    def __next__(self):
        if self.index < len(self.files):
            file = self.files[self.index]
            self.index += 1
            return file
        raise StopIteration

# Использование в for
for file in DirectoryIterator('/path/to/dir'):
    print(file)

Пример 2: Итератор с фильтром

class FilterIterator:
    def __init__(self, data, predicate):
        self.data = iter(data)
        self.predicate = predicate
    
    def __iter__(self):
        return self
    
    def __next__(self):
        while True:
            item = next(self.data)  # Может выбросить StopIteration
            if self.predicate(item):
                return item

# Использование
evens = FilterIterator(range(10), lambda x: x % 2 == 0)
for num in evens:
    print(num)  # 0, 2, 4, 6, 8

Пример 3: Чтение большого файла

class ChunkIterator:
    def __init__(self, filepath, chunk_size=1024):
        self.filepath = filepath
        self.chunk_size = chunk_size
        self.file = None
    
    def __iter__(self):
        self.file = open(self.filepath, 'rb')
        return self
    
    def __next__(self):
        chunk = self.file.read(self.chunk_size)
        if chunk:
            return chunk
        self.file.close()
        raise StopIteration

# Использование в for
for chunk in ChunkIterator('large_file.bin'):
    process_chunk(chunk)

7. iter() и next() функции

# iter() вызывает __iter__() объекта
my_list = [1, 2, 3]
iterator = iter(my_list)
print(type(iterator))  # <class 'list_iterator'>

# next() вызывает __next__() итератора
print(next(iterator))  # 1
print(next(iterator))  # 2
print(next(iterator))  # 3
# next(iterator)  # StopIteration

# Дефолтное значение для next()
print(next(iterator, "Done"))  # Done

8. Создание итератора из функции

class FunctionIterator:
    def __init__(self, func, *args):
        self.func = func
        self.args = args
    
    def __iter__(self):
        return self
    
    def __next__(self):
        try:
            return self.func(*self.args)
        except StopIteration:
            raise

# Или проще — используй генератор!
def my_iterator(n):
    for i in range(n):
        yield i

for i in my_iterator(5):
    print(i)  # 0, 1, 2, 3, 4

9. iter() с двумя аргументами

Это может создать итератор из callable:

import random

# Создаём итератор из функции
random_iter = iter(lambda: random.randint(1, 10), 7)

# Будет вызывать lambda пока не вернёт 7
for num in random_iter:
    print(num)  # Будет печатать случайные числа до 7

# Это работает с любой функцией
def read_stdin():
    line = input()
    return line if line else None

for line in iter(read_stdin, None):
    print(f"Введено: {line}")

10. Почему это важно

Понимание работы итераторов критично для:

# List comprehension использует итератор
result = [x * 2 for x in iterator]

# Generator expression использует итератор
result = (x * 2 for x in iterator)

# map/filter используют итераторы
result = map(lambda x: x * 2, iterator)
result = filter(lambda x: x > 5, iterator)

# zip использует итераторы
for a, b in zip(iter1, iter2):
    print(a, b)

# Распаковка использует итератор
a, b, c = iterator

Резюме

Да, можно передать итератор в for цикл! На самом деле:

  1. for цикл ожидает итератор или итерируемое
  2. Если передать итерируемое, for превратит его в итератор через iter()
  3. Если передать уже итератор, for использует его напрямую
  4. Итератор имеет методы __iter__() и __next__()
  5. Итератор истощается после использования (нельзя использовать дважды)
  6. Для повторного использования нужно создать новый итератор

Важный совет: Если нужно использовать данные несколько раз в for цикле, используй итерируемое (список, кортеж, генератор), а не итератор.