Инструмент для порождения чисел
range() делает ровно одну вещь — производит последовательность целых чисел. Это главный напарник for-циклов, когда нужно проитерироваться заданное число раз или пройтись по числовому интервалу.
Самая простая форма принимает один аргумент — stop:
Вывод:
0
1
2
3
4
Две детали, которые ловят новичков:
- Счёт начинается с 0.
range(5)даёт пять чисел, начиная с 0. - Значение stop исключается.
range(5)останавливается перед 5 — само 5 не входит.
Эти правила согласуются по всему Python — в срезах, индексации и range. Как только усвоишь «stop не входит», спотыкаться перестанешь.
Три формы
range() принимает один, два или три аргумента:
Step — это размер каждого скачка. range(0, 20, 4) выдаёт каждое четвёртое число. Держи это в голове в следующий раз, когда нужно «каждый второй элемент» или «каждый десятый сэмпл».
Счёт в обратную сторону
Шаг может быть отрицательным, и тогда ты считаешь назад:
Опять же, stop исключается — range(10, 0, -1) останавливается перед 0, а не на 0. Чтобы включить 0, поставь stop равным -1:
range ленив
В Python 3 range() не строит список чисел в памяти. Он возвращает лёгкий range-объект, который производит числа по одному по требованию. Поэтому ты можешь писать:
Миллиард-числовой «range» занимает фактически ноль памяти. Числа генерируются тогда, когда цикл их просит.
Если список чисел действительно нужен — чтобы модифицировать, отсортировать или индексировать за пределами базового — конвертируй явно:
Чаще всего список не нужен. for i in range(...) работает напрямую.
Типичные паттерны
Горстка рецептов, которые ты будешь использовать постоянно:
Сделать что-то n раз.
_ — соглашение со значением «это значение мне не интересно»: Python его не навязывает, но любой читатель поймёт намерение.
Индексировать по последовательности.
Предпочитай enumerate() вместо range(len(...)), но если нужен именно индекс:
Всё равно в большинстве случаев enumerate(items) чище.
Проходить через каждый второй элемент.
Выведет a, c, e. Для простого прореживания, впрочем, синтаксис срезов ещё прямее: items[::2].
Быстро получить числовой список.
Это списковое включение — о нём позже, — но числа поставляет range.
Чем range() не является
Два острых края, которые стоит знать:
rangeпроизводит только целые. Если нужен вещественный шаг (например, от 0.0 до 1.0 с шагом 0.1) — используйnumpy.arangeили цикл со своим счётчиком.rangeне работает с произвольными итерируемыми. Он строго для целых чисел. Если ты пытаешься «range-нуть» по списку — тебе нуженenumerateили просто сам список.
Собираем вместе
Небольшой пример, использующий несколько вариаций разом:
Два вложенных цикла на range, дающие сетку. Заметь, что оба цикла стартуют с 1 — range(1, 6), — потому что мы хотим метки от 1 до 5.
Переходим к коллекциям
Ты уже видел условия, оба типа циклов и range. Этого достаточно, чтобы управлять любой коллекцией. Следующая глава — сами коллекции: списки, кортежи, множества и словари.
Часто задаваемые вопросы
Что делает range() в Python?
range() производит последовательность целых чисел. range(n) даёт числа от 0 до n-1. range(start, stop) — целые от start до, но не включая stop. range(start, stop, step) позволяет выбрать шаг, включая отрицательный для счёта в обратную сторону.
range() создаёт список?
range() создаёт список?Нет. В Python 3 range() возвращает лёгкий range-объект, генерирующий числа по требованию. Поэтому range(10**9) мгновенен — он не выделяет миллиард целых. Оберни в list(...), если список действительно нужен.
Как считать в обратную сторону с range()?
Используй отрицательный шаг: range(10, 0, -1) даёт 10, 9, 8, ..., 1. Помни, что stop всегда исключается, так что чтобы включить 0, пиши range(10, -1, -1).