← Назад к вопросам
Какой метод отвечает за получение следующего элемента в итераторе?
2.2 Middle🔥 181 комментариев
#Python Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Какой метод отвечает за получение следующего элемента в итераторе
Метод __next__() отвечает за получение следующего элемента в итераторе. Это специальный метод (dunder method), который вызывается встроенной функцией next() или в цикле for.
Основной механизм
# __next__() — это метод итератора
class Counter:
def __init__(self, max):
self.current = 0
self.max = max
def __iter__(self):
"""Возвращает сам итератор."""
return self
def __next__(self):
"""Получает следующий элемент."""
if self.current >= self.max:
raise StopIteration # Сигнал конца итерации
self.current += 1
return self.current
# Использование
counter = Counter(3)
# Вариант 1: явный вызов next()
print(next(counter)) # 1 — вызывает __next__()
print(next(counter)) # 2
print(next(counter)) # 3
# next(counter) # Вызовет StopIteration
# Вариант 2: цикл for (неявно вызывает __next__())
counter2 = Counter(3)
for num in counter2:
print(num) # 1, 2, 3
StopIteration — сигнал конца
Когда next() больше не может вернуть элемент, оно должно поднять исключение StopIteration:
class Range:
def __init__(self, max):
self.current = 0
self.max = max
def __iter__(self):
return self
def __next__(self):
if self.current >= self.max:
raise StopIteration # Конец итерации
self.current += 1
return self.current
# Демонстрация
r = Range(2)
print(next(r)) # 1
print(next(r)) # 2
try:
print(next(r)) # Вызывает StopIteration
except StopIteration:
print("Итератор исчерпан")
Iterator vs Iterable
Важно различать два понятия:
# Iterable — объект, который ИМЕЕТ __iter__()
# Возвращает итератор
list_items = [1, 2, 3] # Iterable
iterator = iter(list_items) # Получили итератор через __iter__()
# Iterator — объект, который ИМЕЕТ __iter__() и __next__()
# Может получать следующий элемент
class MyIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self): # Iterable
return self
def __next__(self): # Iterator — получает следующий элемент
if self.index >= len(self.data):
raise StopIteration
value = self.data[self.index]
self.index += 1
return value
my_iter = MyIterator([10, 20, 30])
print(next(my_iter)) # 10 — вызвало __next__()
print(next(my_iter)) # 20
print(next(my_iter)) # 30
Использование в цикле for
class Alphabet:
def __init__(self, letters):
self.letters = letters
self.index = 0
def __iter__(self):
return self # Возвращает итератор (сам себя)
def __next__(self):
if self.index >= len(self.letters):
raise StopIteration
letter = self.letters[self.index]
self.index += 1
return letter
# Цикл for неявно вызывает:
# 1. __iter__() чтобы получить итератор
# 2. __next__() для каждой итерации
# 3. Ловит StopIteration чтобы завершить цикл
alphabet = Alphabet('ABC')
for char in alphabet:
print(char) # A, B, C
Встроенные итераторы Python
# List
list_iter = iter([1, 2, 3])
print(next(list_iter)) # 1 — вызвало __next__() встроенного класса list_iterator
print(next(list_iter)) # 2
# String
str_iter = iter("ABC")
print(next(str_iter)) # 'A'
print(next(str_iter)) # 'B'
# Range
range_iter = iter(range(3))
print(next(range_iter)) # 0
print(next(range_iter)) # 1
# Dict
dict_iter = iter({'a': 1, 'b': 2})
print(next(dict_iter)) # 'a' (ключи)
print(next(dict_iter)) # 'b'
# Enumerate
enum_iter = iter(enumerate(['x', 'y']))
print(next(enum_iter)) # (0, 'x')
print(next(enum_iter)) # (1, 'y')
Generator — особый тип итератора
Генератор — это функция, которая использует yield вместо return. Она автоматически имеет __iter__() и __next__():
# Обычный итератор
class FileReader:
def __init__(self, filename):
self.file = open(filename)
def __iter__(self):
return self
def __next__(self):
line = self.file.readline()
if not line:
raise StopIteration
return line
# Генератор — то же самое, но проще
def file_reader(filename):
with open(filename) as f:
for line in f:
yield line # yield — это return, но сохраняет состояние
# Использование (одинаковое)
for line in file_reader('data.txt'):
print(line)
Практические примеры
Пример 1: Итератор по файлу
class FileIterator:
def __init__(self, filename):
self.file = open(filename, 'r')
self.closed = False
def __iter__(self):
return self
def __next__(self):
line = self.file.readline()
if not line:
self.file.close()
self.closed = True
raise StopIteration # Конец файла
return line.strip()
# Использование
for line in FileIterator('config.txt'):
print(f"Config: {line}")
Пример 2: Итератор с состоянием
class Fibonacci:
def __init__(self, limit):
self.limit = limit
self.a, self.b = 0, 1
def __iter__(self):
return self
def __next__(self):
if self.a > self.limit:
raise StopIteration
value = self.a
self.a, self.b = self.b, self.a + self.b
return value
# Использование
for num in Fibonacci(100):
print(num) # 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89
Пример 3: Итератор по БД
class DatabaseIterator:
def __init__(self, db_connection, query):
self.cursor = db_connection.cursor()
self.cursor.execute(query)
def __iter__(self):
return self
def __next__(self):
row = self.cursor.fetchone()
if row is None:
self.cursor.close()
raise StopIteration
return row
# Использование
db = sqlite3.connect('data.db')
for row in DatabaseIterator(db, "SELECT * FROM users"):
print(row)
Особенности next()
class SafeIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
# Не рекомендуется использовать try/except для контроля flow
# ❌ Плохо
try:
value = self.data[self.index]
self.index += 1
return value
except IndexError:
raise StopIteration
# ✅ Хорошо
if self.index >= len(self.data):
raise StopIteration
value = self.data[self.index]
self.index += 1
return value
# Важно: __next__() должно быть эффективным
# Каждый вызов — это потенциально дорогая операция
Как Python вызывает next()
class Demo:
def __init__(self):
self.count = 0
def __iter__(self):
print("__iter__() вызван")
return self
def __next__(self):
print(f"__next__() вызван (count={self.count})")
if self.count >= 2:
raise StopIteration
self.count += 1
return self.count
print("Начало цикла:")
for val in Demo():
print(f"Получено значение: {val}")
# Вывод:
# Начало цикла:
# __iter__() вызван
# __next__() вызван (count=0)
# Получено значение: 1
# __next__() вызван (count=1)
# Получено значение: 2
# __next__() вызван (count=2) <- Вызовет StopIteration
Заключение
__next__() — это метод, который:
- Отвечает за получение следующего элемента итератора
- Вызывается неявно функцией
next()и цикломfor - Должен поднимать
StopIterationкогда элементы закончились - Работает вместе с
__iter__()для создания итерируемого объекта
Это фундаментальный механизм Python для работы с последовательностями и потоками данных.