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

Является ли range итератором?

1.8 Middle🔥 141 комментариев
#Python Core

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

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

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

# Является ли range итератором?

Короткий ответ: НЕТ. range — это итерируемый объект, а не итератор.

Разница

# range — ИТЕРИРУЕМЫЙ объект (есть __iter__)
r = range(5)
print(hasattr(r, '__iter__'))   # True
print(hasattr(r, '__next__'))   # False — нет этого метода!

# Это значит: range можно использовать в for цикле,
# но это не итератор

Как это работает

# range — итерируемый
r = range(3)

# Для итерации нужно создать итератор
iterator = iter(r)  # Создаём итератор из range
print(type(iterator))  # <class 'range_iterator'>

# Теперь можем использовать next()
print(next(iterator))  # 0
print(next(iterator))  # 1
print(next(iterator))  # 2
# print(next(iterator))  # StopIteration

Под капотом for цикла

# Когда пишешь
for i in range(3):
    print(i)

# Python делает
iterator = iter(range(3))  # Создаёт итератор
while True:
    try:
        i = next(iterator)
        print(i)
    except StopIteration:
        break

Проверка методов

r = range(5)

# Есть __iter__
print(r.__iter__)  # <method-wrapper '__iter__' of range object>

# НЕТ __next__
print(r.__next__)  # AttributeError: 'range' object has no attribute '__next__'

# Сравни с итератором
it = iter(r)
print(it.__iter__)  # <method-wrapper '__iter__' of range_iterator object>
print(it.__next__)  # <method-wrapper '__next__' of range_iterator object>

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

1. range можно итерировать много раз

r = range(3)

# Первый раз
for i in r:
    print(i)  # 0, 1, 2

# Второй раз (работает!)
for i in r:
    print(i)  # 0, 1, 2 (снова)

2. Итератор исчерпывается после использования

it = iter(range(3))

# Первая итерация
for i in it:
    print(i)  # 0, 1, 2

# Вторая попытка
for i in it:
    print(i)  # Ничего не выведет (итератор исчерпан)

Другие примеры

# ИТЕРИРУЕМЫЕ (но не итераторы)
list([1, 2, 3])         # есть __iter__, нет __next__
str("hello")            # есть __iter__, нет __next__
dict({"a": 1})          # есть __iter__, нет __next__
set([1, 2, 3])          # есть __iter__, нет __next__
range(10)               # есть __iter__, нет __next__

# ИТЕРАТОРЫ (имеют оба метода)
iter([1, 2, 3])         # есть __iter__ и __next__
iter("hello")           # есть __iter__ и __next__
iter({"a": 1})          # есть __iter__ и __next__
open("file.txt")        # есть __iter__ и __next__
(x for x in range(3))   # генератор — есть оба

Оптимизация в Python 3

# range очень эффективен — не хранит все числа в памяти
r = range(1000000)
print(r)  # range(0, 1000000) — просто объект, без памяти на числа

# Списки, наоборот, хранят всё
l = list(range(1000000))
print(l)  # [0, 1, 2, ...] — использует 40+ МБ памяти

Это одна из причин, почему range лучше использовать, чем list(range(...)) в цикле.

Быстрая проверка

# Функция для проверки типа объекта
def check_type(obj):
    is_iterable = hasattr(obj, '__iter__')
    is_iterator = hasattr(obj, '__next__')
    
    if is_iterator:
        return "Это ИТЕРАТОР"
    elif is_iterable:
        return "Это ИТЕРИРУЕМЫЙ (но не итератор)"
    else:
        return "Это не итерируемый и не итератор"

print(check_type(range(5)))     # Это ИТЕРИРУЕМЫЙ (но не итератор)
print(check_type(iter(range(5)))) # Это ИТЕРАТОР
print(check_type([1, 2, 3]))    # Это ИТЕРИРУЕМЫЙ (но не итератор)
print(check_type(iter([1, 2]))) # Это ИТЕРАТОР
print(check_type(42))           # Это не итерируемый и не итератор

Вывод

rangeИТЕРИРУЕМЫЙ объектrangeНЕ ИТЕРАТОРiter(range(...))ИТЕРАТОРrange можно итерировать несколько раз ✅ range очень экономный (не хранит значения в памяти)

Это одна из самых частых ошибок на собеседованиях — путаница между итерируемыми объектами и итераторами.