Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Как устроен range в Python?
range() — это встроенный тип данных в Python, который представляет неизменяемую последовательность целых чисел. Вопреки частому заблуждению, это не список, а специальный объект, который генерирует числа по требованию.
Структура и принцип работы
range — это итерируемый объект, который хранит только три параметра: start, stop и step. Сами числа не генерируются заранее; они создаются на лету при итерации. Это ключевая фишка, обеспечивающая эффективность:
# Все эти варианты создают объект range, а не список
r1 = range(10) # от 0 до 9
r2 = range(2, 10) # от 2 до 9
r3 = range(0, 10, 2) # от 0 до 8 с шагом 2
r4 = range(10, 0, -1) # от 10 до 1, в обратном порядке
print(r1) # range(0, 10)
print(type(r1)) # <class "range">
Ленивое вычисление
Это ленивая (lazy) последовательность. Числа вычисляются только при обращении:
# Создание range НЕ использует память для хранения всех чисел
big_range = range(1000000000) # можно создать без проблем
print(sys.getsizeof(big_range)) # только 48 байт!
# А вот список потребует миллиарды байт
big_list = list(range(1000000000)) # MemoryError!
Внутренние параметры
Кажды объект range содержит:
class range:
def __init__(self, start, stop=None, step=1):
# start, stop, step хранятся как атрибуты
# При stop=None, значение start становится stop, а start=0
Отсюда сложность:
range(5) # start=0, stop=5, step=1
range(2, 5) # start=2, stop=5, step=1
range(0, 10, 3) # start=0, stop=10, step=3
Методы доступа
range поддерживает индексацию и срезы без конвертации в список:
r = range(10)
print(r[0]) # 0
print(r[5]) # 5
print(r[-1]) # 9
print(len(r)) # 10
print(5 in r) # True - O(1) операция!
# Проверка принадлежности работает через формулу,
# а не перебором (как в списке)
Итерация
Для итерации используется __iter__() и __next__():
for num in range(5):
print(num)
# Эквивалентно:
it = iter(range(5)) # создаёт объект-итератор
while True:
try:
print(next(it))
except StopIteration:
break
Производительность
Вот почему range мощнее списка:
import sys
# range занимает константное место в памяти
print(sys.getsizeof(range(1000000))) # ~48 байт
# список занимает линейное место
print(sys.getsizeof(list(range(1000000)))) # ~9 мегабайт
# Проверка принадлежности O(1) для range, O(n) для списка
rng = range(10000000)
print(9999999 in rng) # быстро
lst = list(range(10000000))
print(9999999 in lst) # медленнее
Практическое применение
# Эффективные циклы
for i in range(1000000): # не создаёт список
print(i)
# Двойная итерация
for i in range(3):
for j in range(3):
print(f"({i}, {j})")
# Обратный порядок
for i in range(10, 0, -1):
print(i) # 10, 9, 8, ..., 1
range — это элегантное решение Python для оптимизации памяти при работе с последовательностями целых чисел. Это один из примеров, почему Python так популярен в Data Science — встроенные типы хорошо оптимизированы.