TGViewer
Библиотека питониста | Python, Django, Flask Библиотека питониста | Python, Django, Flask @pyproglib · 37.3K subscribers
Post #7477 3.09K
👀 Почему ваш кастомный range «одноразовый»

На собеседованиях по Python любят давать задачу: реализовать класс, который ведет себя как встроенный range.

❌ В чем ошибка?

Чаще всего реализуют класс, который является одновременно и итерируемым объектом (`Iterable`), и итератором (`Iterator`):

class RangeLike:
def __init__(self, start, stop):
self.start, self.stop = start, stop
self.current = start

def __iter__(self):
return self # Возвращаем сам объект

def __next__(self):
if self.current < self.stop:
val = self.current
self.current += 1
return val
raise StopIteration



Проблема: При первом проходе list(r) состояние self.current доходит до максимума. Так как объект «хранит» свой прогресс внутри себя, второй вызов вернет пустой список. Итераторы в Python — одноразовые.

✅ Как сделать правильно?

Нужно разделить контейнер (который хранит границы) и итератор (который хранит текущее состояние обхода). При каждом вызове __iter__ контейнер должен создавать новый экземпляр итератора:

class RangeIterator:
def __init__(self, start, stop):
self.current, self.stop = start, stop

def __iter__(self): return self

def __next__(self):
if self.current < self.stop:
val = self.current
self.current += 1
return val
raise StopIteration

class RangeLike:
def __init__(self, start, stop):
self.start, self.stop = start, stop

def __iter__(self):
# Каждый раз создаем свежий итератор
return RangeIterator(self.start, self.stop)



В Python существует четкое разделение ролей:

1. Iterable (Итерируемый объект): Это «записная книжка». В ней есть данные, но она не знает, на какой странице вы сейчас читаете. Пример: list, dict, range.
2. Iterator (Итератор): Это «палец», который указывает на текущую строку. У него есть состояние, и он движется только вперед.

Встроенный range — это именно Iterable. Когда вы запускаете цикл for, Python вызывает iter(range_obj), который генерирует новый «палец»-итератор. Именно поэтому по range можно проходить бесконечное количество раз.

💡 Лайфхак: Самый простой способ сделать объект ре-итерируемым в современном Python — использовать генератор внутри __iter__:

def __iter__(self):
curr = self.start
while curr < self.stop:
yield curr
curr += 1


📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека питониста

#буст
  • 👍 15
  • ❤ 4
More from @pyproglib
  1. Sep 30, 2026🔥 Последний день для разработчиков AI уже пишет код. Теперь важнее научиться встраивать е…
  2. Sep 25, 2026🔥 Курс «ИИ для разработчиков» уже стартовал И мы решили открыть первое занятие всем — мож…
  3. Sep 20, 2026👻 94% токенов уходят не на код Анализ запусков показал: основная часть токенов уходит на…
  4. Sep 19, 2026📚Напоминаем про наш полный курс «Самоучитель по Python для начинающих» Мы написали и собр…
  5. Sep 15, 2026😭 Как не потратить недельный лимит AI-кодинга за три дня? Разберём на вебинаре, как трати…
  6. Sep 15, 2026⏱️ Справочник по Big-O в Python Для тех, кто хочет писать не просто работающий, а эффектив…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →