← Назад к вопросам
В чем разница между итератором и итерируемым объектом?
2.0 Middle🔥 181 комментариев
#Python Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Итератор vs Итерируемый объект
Это фундаментальная концепция в Python, которую часто путают. Но разница простая и важная:
- Итерируемый объект (Iterable) — объект, у которого есть метод
__iter__(). Он говорит: "Я могу дать тебе итератор". - Итератор (Iterator) — объект, у которого есть методы
__iter__()и__next__(). Он говорит: "Я умею переходить к следующему элементу".
Зависимость
Iterable ──iter()──> Iterator ──next()──> Element
Каждый итератор является итерируемым (имеет __iter__), но не каждый итерируемый объект — итератор.
Итерируемый объект
Определение: объект с методом __iter__(), который возвращает итератор.
class MyIterable:
def __init__(self, data):
self.data = data
def __iter__(self):
"""Возвращает итератор"""
return iter(self.data) # или MyIterator(self.data)
# Использование
obj = MyIterable([1, 2, 3])
for item in obj: # for вызовет __iter__
print(item)
Примеры встроенных итерируемых объектов:
for item in [1, 2, 3]: # list — итерируемый
pass
for char in "hello": # str — итерируемый
pass
for num in range(5): # range — итерируемый
pass
for key in {a: 1, b: 2}: # dict — итерируемый
pass
Проверка, является ли объект итерируемым:
from collections.abc import Iterable
print(isinstance([1, 2, 3], Iterable)) # True
print(isinstance("hello", Iterable)) # True
print(isinstance(42, Iterable)) # False
Итератор
Определение: объект с методами __iter__() и __next__(). Вызов __next__() возвращает следующий элемент или вызывает StopIteration.
class MyIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
"""Возвращает самого себя"""
return self
def __next__(self):
"""Возвращает следующий элемент"""
if self.index < len(self.data):
result = self.data[self.index]
self.index += 1
return result
else:
raise StopIteration # Конец итерации
# Использование
it = MyIterator([1, 2, 3])
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
print(next(it)) # StopIteration
Примеры встроенных итераторов:
it = iter([1, 2, 3]) # Встроенный итератор
print(next(it)) # 1
print(next(it)) # 2
it = iter("ABC")
print(next(it)) # A
Проверка, является ли объект итератором:
from collections.abc import Iterator
it = iter([1, 2, 3])
print(isinstance(it, Iterator)) # True
print(isinstance([1, 2, 3], Iterator)) # False — это только итерируемый
Визуальное сравнение
# Итерируемый объект — как книга
book = ["chapter1", "chapter2", "chapter3"]
# Итератор — как закладка в книге
reader = iter(book)
while True:
try:
chapter = next(reader) # Закладка переходит на следующую главу
print(f"Читаю: {chapter}")
except StopIteration:
print("Книга прочитана")
break
Цикл for под капотом
# Эта конструкция
for item in [1, 2, 3]:
print(item)
# На самом деле работает так:
it = iter([1, 2, 3]) # Вызывает __iter__
while True:
try:
item = next(it) # Вызывает __next__
print(item)
except StopIteration:
break
Практический пример: Пользовательский итератор
Итератор для файла, читающий блоками:
class FileChunkIterator:
def __init__(self, filename, chunk_size=1024):
self.filename = filename
self.chunk_size = chunk_size
self.file = None
def __iter__(self):
self.file = open(self.filename, rb)
return self
def __next__(self):
chunk = self.file.read(self.chunk_size)
if chunk:
return chunk
else:
self.file.close()
raise StopIteration
# Использование
for chunk in FileChunkIterator(large_file.bin, chunk_size=8192):
process(chunk) # Обрабатываем по частям, не загружая всё в память
Практический пример: Итерируемый объект
Связанный список с поддержкой итерации:
class LinkedListNode:
def __init__(self, value):
self.value = value
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def append(self, value):
if not self.head:
self.head = LinkedListNode(value)
else:
current = self.head
while current.next:
current = current.next
current.next = LinkedListNode(value)
def __iter__(self):
"""Возвращает итератор"""
return LinkedListIterator(self.head)
class LinkedListIterator:
def __init__(self, head):
self.current = head
def __iter__(self):
return self
def __next__(self):
if self.current is None:
raise StopIteration
value = self.current.value
self.current = self.current.next
return value
# Использование
ll = LinkedList()
ll.append(1)
ll.append(2)
ll.append(3)
for value in ll: # Итерируемый объект
print(value) # 1, 2, 3
Генераторы как итераторы
Генераторы — это удобный способ создать итератор:
# Вместо создания класса итератора
class RangeIterator:
def __init__(self, n):
self.n = n
self.i = 0
def __iter__(self):
return self
def __next__(self):
if self.i < self.n:
self.i += 1
return self.i - 1
raise StopIteration
# Можно просто написать
def my_range(n):
i = 0
while i < n:
yield i
i += 1
# Генератор одновременно итерируемый и итератор
gen = my_range(3)
print(next(gen)) # 0
print(next(gen)) # 1
Таблица сравнения
| Свойство | Итерируемый | Итератор |
|---|---|---|
__iter__() | ✅ Есть | ✅ Есть |
__next__() | ❌ Нет | ✅ Есть |
Возвращает из __iter__() | Новый итератор | Самого себя (self) |
| Использование в for | ✅ Да | ✅ Да |
| next() | ❌ Ошибка | ✅ Работает |
| Пример | list, str, dict | iter(list), генератор |
Итоги
- Итерируемый объект — это инструмент, например, полка с книгами. На нём есть способ их упорядочить (
__iter__). - Итератор — это процесс чтения. Он знает, какая книга была последней, и какая будет следующей (
__next__). - Каждый итератор — итерируемый, но не наоборот.
- Генераторы — это синтаксический сахар для создания итераторов.
- Понимание разницы критично для работы с потоками данных, которые нельзя загрузить в память целиком.