Django-Admin.ru

Функция range() в Python: синтаксис и примеры

Функция range() в Python: параметры start, stop и step, обратный отсчёт, range в цикле for, почему не входит правая граница и как получить список чисел.

Редакция Django-Admin.ru
· обновлено · 9 мин чтения

Содержание · 10 разделов
  1. Синтаксис range: start, stop, step
  2. range(stop): числа от нуля
  3. range(start, stop): свой диапазон
  4. Шаг step
  5. Обратный отсчёт: отрицательный шаг
  6. Что возвращает range
  7. range почти не занимает памяти
  8. range — полноценная последовательность
  9. range в цикле for
  10. range(len()) или enumerate
  11. Списки из range
  12. Частые ошибки
  13. Ожидание, что stop входит в диапазон
  14. Дробный шаг или дробные границы
  15. Строка вместо числа
  16. Нулевой шаг
  17. Пустой диапазон при обратном отсчёте
  18. Удаление элементов в цикле по range(len())
  19. Сравнение range со списком
  20. Частые вопросы
  21. Как перебрать буквы алфавита через range?
  22. Как проверить, что число входит в диапазон?
  23. Как сделать бесконечный range?
  24. Почему stop не входит в диапазон?
  25. Можно ли изменить i внутри цикла for i in range?
  26. Итог

Функция range() в Python создаёт последовательность целых чисел — чаще всего для цикла for. Короткий ответ: range(5) даёт числа от 0 до 4, range(2, 7) — от 2 до 6, а range(0, 10, 3) — 0, 3, 6, 9. Правая граница stop в последовательность не входит.

print(list(range(5)))         # → [0, 1, 2, 3, 4]
print(list(range(2, 7)))      # → [2, 3, 4, 5, 6]
print(list(range(0, 10, 3)))  # → [0, 3, 6, 9]

Ниже — все три формы вызова, обратный отсчёт, свойства объекта range и типичные ошибки. Примеры проверены на Python 3.12; вывод показан комментарием # →.

Синтаксис range: start, stop, step

У range() три формы вызова:

range(stop)
range(start, stop)
range(start, stop, step)
ПараметрПо умолчаниюЧто означает
start0первое число последовательности (включительно)
stop—граница, до которой идёт счёт (не включается)
step1шаг; может быть отрицательным, но не нулём

Все аргументы — целые числа. Именованные аргументы не поддерживаются: range(stop=5) не сработает, только позиционные.

range(stop): числа от нуля

С одним аргументом счёт начинается с нуля и заканчивается на stop - 1. Так range(n) даёт ровно n чисел — поэтому его удобно использовать, чтобы повторить действие n раз:

for i in range(3):
    print(i)
0
1
2

range(start, stop): свой диапазон

print(list(range(1, 11)))   # → [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(list(range(-3, 3)))   # → [-3, -2, -1, 0, 1, 2]
print(list(range(5, 5)))    # → []
print(list(range(5, 1)))    # → []

Чтобы включить правую границу, прибавьте к ней единицу: числа от 1 до n включительно — это range(1, n + 1). Если start не меньше stop, диапазон пуст и цикл не выполнится ни разу — без ошибки.

Шаг step

Третий аргумент задаёт шаг между числами:

print(list(range(0, 20, 5)))  # → [0, 5, 10, 15]
print(list(range(1, 10, 2)))  # → [1, 3, 5, 7, 9]   нечётные
print(list(range(2, 11, 2)))  # → [2, 4, 6, 8, 10]  чётные

Обратный отсчёт: отрицательный шаг

С отрицательным шагом range считает вниз, а start должен быть больше stop:

print(list(range(10, 0, -1)))   # → [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
print(list(range(10, 0, -3)))   # → [10, 7, 4, 1]
print(list(range(5, -1, -1)))   # → [5, 4, 3, 2, 1, 0]
print(list(range(0, 10, -1)))   # → []

Чтобы дойти до нуля включительно, stop ставят на единицу ниже: range(5, -1, -1). Тот же результат проще получить через reversed() или срез:

print(list(reversed(range(5))))  # → [4, 3, 2, 1, 0]
print(range(5)[::-1])            # → range(4, -1, -1)

Что возвращает range

range() возвращает не список, а особый объект типа range. Он не хранит числа, а вычисляет их по запросу, поэтому print() показывает только параметры:

r = range(5)
print(r)           # → range(0, 5)
print(type(r))     # → <class 'range'>
print(list(r))     # → [0, 1, 2, 3, 4]
print(tuple(range(3)))  # → (0, 1, 2)

Чтобы увидеть числа или получить настоящий список, оберните range в list().

range почти не занимает памяти

Размер объекта range не зависит от длины диапазона — хранятся только start, stop и step. На 64-битном Python 3.12:

import sys
big = range(10 ** 9)
print(len(big))                    # → 1000000000
print(sys.getsizeof(big))          # → 48
print(sys.getsizeof(list(range(1000))))  # → 8056

Миллиард чисел в range занимает 48 байт, а список всего из тысячи чисел — больше 8 КБ (и это без памяти под сами числа).

range — полноценная последовательность

С объектом range работают индексы, срезы, len(), in, sum(), max() — все общие операции последовательностей, кроме склейки + и повторения *:

r = range(0, 100, 10)
print(len(r))        # → 10
print(r[2])          # → 20
print(r[-1])         # → 90
print(r[2:5])        # → range(20, 50, 10)
print(50 in r)       # → True
print(55 in r)       # → False
print(r.index(70))   # → 7
print(r.start, r.stop, r.step)  # → 0 100 10
print(sum(range(1, 101)))  # → 5050
print(max(range(3, 8)))    # → 7

Проверка in для целого числа вычисляется по формуле, а не перебором, поэтому 999_999_999 in range(10 ** 9) отвечает мгновенно.

Примечание: в Python 2 функция range() возвращала список, а «ленивой» была xrange(). В Python 3 xrange нет — range сам работает лениво.

range в цикле for

Основное применение range — счётный цикл:

total = 0
for n in range(1, 6):
    total += n
print(total)  # → 15

for _ in range(3):
    print("Привет")
15
Привет
Привет
Привет

Переменная _ — соглашение для случая, когда номер итерации не нужен. Вложенные циклы с range строят таблицы:

for i in range(1, 4):
    print(*[i * j for j in range(1, 6)], sep="\t")
1	2	3	4	5
2	4	6	8	10
3	6	9	12	15

range(len()) или enumerate

Обход индексов списка через range(len(...)) работает, но если нужны и индекс, и элемент, читаемее enumerate:

fruits = ["яблоко", "груша", "слива"]
for i in range(len(fruits)):
    print(i, fruits[i])
for i, fruit in enumerate(fruits):  # то же самое, но короче
    print(i, fruit)

range(len(...)) оправдан, когда нужен доступ к соседним элементам по индексу:

nums = [3, 8, 2, 9]
for i in range(len(nums) - 1):
    print(nums[i], nums[i + 1])
3 8
8 2
2 9

Списки из range

range часто служит источником для генератора списка:

squares = [n ** 2 for n in range(1, 6)]
print(squares)  # → [1, 4, 9, 16, 25]
evens = list(range(0, 11, 2))
print(evens)    # → [0, 2, 4, 6, 8, 10]

Частые ошибки

Ожидание, что stop входит в диапазон

range(1, 10) заканчивается на 9, а не на 10. Это самая частая ошибка «на единицу». Нужна граница включительно — пишите range(1, n + 1).

Дробный шаг или дробные границы

range(0, 1, 0.1)  # → TypeError: 'float' object cannot be interpreted as an integer

range работает только с целыми числами. Для дробного шага пересчитайте целые значения:

steps = [i / 10 for i in range(0, 5)]
print(steps)  # → [0.0, 0.1, 0.2, 0.3, 0.4]

Для численных расчётов есть numpy.arange() и numpy.linspace() — о них в статье о NumPy.

Строка вместо числа

input() возвращает строку, поэтому range(input()) падает с ошибкой TypeError: 'str' object cannot be interpreted as an integer. Преобразуйте ввод в число: range(int(input())).

Нулевой шаг

range(0, 10, 0)  # → ValueError: range() arg 3 must not be zero

Пустой диапазон при обратном отсчёте

range(0, 10, -1) не выдаёт ошибку — он просто пуст, и цикл не выполнится. При отрицательном шаге start должен быть больше stop.

Удаление элементов в цикле по range(len())

items = [1, 2, 3, 4]
for i in range(len(items)):
    if items[i] % 2 == 0:
        del items[i]  # → IndexError: list index out of range

range(len(items)) вычисляется один раз, а список при удалении становится короче. Соберите новый список: items = [x for x in items if x % 2].

Сравнение range со списком

range(5) == [0, 1, 2, 3, 4] возвращает False: это объекты разных типов. Сравнивайте list(range(5)) со списком или два range между собой — range(0, 3) == range(0, 3, 1) даёт True.

Частые вопросы

Как перебрать буквы алфавита через range?

range работает только с числами, но коды символов — тоже числа. Функция ord() возвращает код символа, chr() — символ по коду:

letters = [chr(code) for code in range(ord("a"), ord("f"))]
print(letters)  # → ['a', 'b', 'c', 'd', 'e']
import string
print(string.ascii_lowercase[:5])  # → abcde

Для латиницы проще взять готовую строку string.ascii_lowercase. С кириллицей приём через коды работает для букв от «а» до «я», но буква «ё» стоит в таблице Unicode отдельно и в такой диапазон не попадает.

Как проверить, что число входит в диапазон?

Для целых чисел подходит x in range(1, 10). Но для дробных он даёт неожиданный результат, поэтому в общем случае надёжнее цепочка сравнений:

x = 3.5
print(1 <= x < 10)       # → True
print(x in range(1, 10)) # → False
print(3 in range(1, 10)) # → True

Как сделать бесконечный range?

У range всегда есть stop. Для бесконечного счёта используйте itertools.count(start, step) и выходите из цикла через break — или напишите цикл while:

from itertools import count
for n in count(10, 5):
    if n > 25:
        break
    print(n)
10
15
20
25

Почему stop не входит в диапазон?

Так длина диапазона равна разности границ: в range(2, 7) ровно 7 - 2 = 5 чисел, а range(n) перебирает все индексы последовательности длиной n. Срезы a[start:stop] устроены так же, поэтому границы range и срезов совпадают.

print(len(range(2, 7)))  # → 5

Можно ли изменить i внутри цикла for i in range?

Можно, но на следующей итерации for всё равно присвоит i очередное число из range. Чтобы пропускать или повторять шаги, используйте continue или цикл while с ручным счётчиком.

for i in range(3):
    print(i, end=" ")
    i += 10
# → 0 1 2

Итог

range(start, stop, step) генерирует целые числа от start до stop не включая, с шагом step; отрицательный шаг даёт обратный отсчёт. Объект range ленивый и почти не занимает памяти, а в список превращается через list(). Как применять его в циклах — в статьях о цикле for и цикле while, а остальной синтаксис — в шпаргалке по Python.

  • #Python
  • #range
  • #Циклы
  • #Синтаксис
  • #Встроенные функции
↑ ↓ выборEnter открытьEsc закрыть