Скидка до 60% и курс по ИИ в подарок 3 дня 09 :37 :59 Выбрать курс
Код
#статьи

Как работает функция range() в Python: от базовых циклов до списковых выражений

Генерируем последовательности чисел и оптимизируем итерации.

Иллюстрация: Оля Ежак для Skillbox Media

Когда требуется выполнить в коде одно и то же действие несколько раз — пройтись по элементам списка, вычислить значения переменной или вывести ряд чисел, — программисты используют цикл for вместе с функцией range ().

Эта функция создаёт диапазоны данных, задаёт шаг между элементами и не требует дополнительной памяти — это ускоряет выполнение кода. В статье мы разберём, как использовать range () в Python для разнообразных задач.

Содержание


Что такое range() в Python

range() — встроенная функция Python, которая создаёт последовательность целых чисел в заданном диапазоне. Она не хранит числа в памяти, а создаёт объект диапазона — специальный тип данных, содержащий только правила построения последовательности: начало, конец и шаг между элементами.

При обращении к объекту Python вычисляет значения на лету — это называется ленивым вычислением. Благодаря этому range() работает быстро и экономит память, даже если диапазон содержит миллионы элементов.

Например, range(1000000) создаёт объект размером всего несколько байт, хотя представляет миллион чисел. Если бы мы создали список из миллиона элементов — list(range (1000000)) — он занял бы около 8 МБ памяти.

Проверим это в работе и создадим последовательность из пяти чисел:

print(range(5))

В ответ получим range(0, 5). Чтобы увидеть конкретные значения, нужно преобразовать диапазон в список:

print(list(range(5)))

Теперь видим всю последовательность: [0, 1, 2, 3, 4].

Обратите внимание, что первым элементом последовательности будет 0. Если требуется явно задать стартовое число, например 1, то это необходимо указать при вызове функции. Это рассмотрим дальше.

Как вызывать функцию range()

Функцию range() можно вызвать тремя способами — в зависимости от того, какие параметры вы передаёте:

range(stop)
range(start, stop)
range(start, stop, step)

Рассмотрим параметры функции:

  • start — число, с которого начинается последовательность (по умолчанию 0);
  • stop — число, до которого считать (не включая его);
  • step — шаг между элементами (по умолчанию 1).

А вот несколько примеров для закрепления:

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

В этих примерах мы используем три встроенные функции: range() создаёт объект диапазона, list() преобразует его в список, а print() выводит результат. Без list() вы увидите только range(0, 5), а без print() код ничего не выведет.

Как использовать range() с циклами

Цикл for в Python — это конструкция, с помощью которой можно выполнять один и тот же блок кода для каждого элемента последовательности. Он будет перебирать их по очереди и повторять действия, пока они не закончатся.

Функция range() в Python часто используется с циклом for: она создаёт последовательность чисел для перебора. Это основной инструмент для повторяющихся действий — от простых подсчётов до сложных алгоритмов.

Напишем такой цикл:

for i in range(5):
    print(i)  # 0, 1, 2, 3, 4

Этот код последовательно подставит в переменную i числа от 0 до 4 и выведет их на экран. Сами числа генерируются с помощью range(5), а цикл for использует каждое из них по очереди.

Можно задать не только количество повторений, но и диапазон значений — с какого числа начать и на каком завершить последовательность:

for i in range(2, 7):
    print(i)  # 2, 3, 4, 5, 6

С помощью range() можно обратиться к элементам списка по индексу:

fruits = ['Xiaomi', 'Samsung', 'Tecno']
for i in range(len(fruits)):
    print(f'Индекс {i}: {fruits[i]}')

Получим следующий результат:

Индекс 0: Xiaomi
Индекс 1: Samsung
Индекс 2: Tecno

Шаг и обратный порядок

У функции range() есть третий параметр — шаг. Он определяет, с каким интервалом изменяется каждое следующее значение в последовательности. Если шаг не задан, Python считает, что он равен 1. Вот пример:

for i in range(0, 10, 2):
    print(i)

Здесь range(0, 10, 2) создаёт числа от 0 до 9 с шагом 2. Результат:

0
2
4
6
8

Можно указать отрицательный шаг, который позволяет двигаться по последовательности в обратном порядке — от большего к меньшему:

for i in range(10, 5, -1):
    print(i)

Функция уменьшает значение на 1 на каждом шаге:

10
9
8
7
6

При отрицательном шаге начальное значение start должно быть больше конечного stop — иначе диапазон будет пустым:

for i in range(0, 10, -1):
    print(i) # Ничего не выведет

Вложенные циклы

Вложенные циклы — это циклы внутри других циклов. Они позволяют выполнять повторяющиеся действия на нескольких уровнях. Например, внешний цикл может перебирать строки, а внутренний — столбцы в таблице. Это полезно для работы с двумерными данными, создания координатных сеток, перебора всех возможных комбинаций элементов из разных списков.

Во вложенных циклах range() управляет количеством повторений на каждом уровне. Рассмотрим пример:

for i in range(3): # Внешний цикл: перебираем три строки
    for j in range(2): # Внутренний цикл: перебираем два столбца 
        print(f'Строка {i}, Столбец {j}') # Выводим координаты каждой ячейки

Вот что получится:

Строка 0, Столбец 0
Строка 0, Столбец 1
Строка 1, Столбец 0
Строка 1, Столбец 1
Строка 2, Столбец 0
Строка 2, Столбец 1

Внешний цикл проходит по строкам, внутренний — по столбцам. Так можно работать с двумерными массивами или рисовать фигуры в консоли.

Для закрепления напишем короткую версию таблицы умножения до 5:

for i in range(1, 6):
    for j in range(1, 6):
        print(i * j, end='\t')
    print()

Внешний цикл управляет строками, а внутренний — столбцами. При выводе мы перемножаем числа из обоих циклов. Чтобы оформить результат в виде таблицы, используем параметр end='\t' — он добавляет табуляцию между элементами. В результате мы получим таблицу умножения от 1 до 5:

1	2	3	4	5	
2	4	6	8	10	
3	6	9	12	15	
4	8	12	16	20	
5	10	15	20	25

С помощью вложенных циклов можно рисовать геометрические фигуры. Например, построим прямоугольник из звёздочек:

for i in range(3):
    for j in range(5):
        print('*', end='')
    print()

Внутренний цикл печатает одну строку из звёздочек, а внешний цикл определяет количество таких строк. Параметр end='' оставляем пустым, чтобы при выводе между элементами не было пробелов или других символов:

*****
*****
*****

Теперь решим задачу посложнее. Напишем код, который создаст приветственные сообщения для каждого человека в двух вариантах:

names = ['Аня', 'Борис', 'Вика']
greetings = ['Привет', 'Здравствуйте']

for name in names:
    for greet in greetings:
        print(f'{greet}, {name}!')

Программа выведет все комбинации приветствий и имён:

Привет, Аня!
Здравствуйте, Аня!
Привет, Борис!
Здравствуйте, Борис!
Привет, Вика!
Здравствуйте, Вика!

Как применять range() с функцией len()

Функция len() в Python возвращает длину объекта — количество элементов в коллекциях: списке, строке, кортеже, словаре и множестве. Функция range(), в свою очередь, создаёт последовательность чисел. Вместе с len() она часто используется для обхода элементов по их индексам — это может пригодиться, когда необходимо не только получить значение элемента, но и узнать его позицию в коллекции или одновременно работать с несколькими списками.

Представим, нам нужно вывести нумерованный список студентов с указанием их баллов. Для этого напишем код и используем в нём range() и len():

grades = [95, 82, 74, 100, 89] # Список баллов студентов

for i in range(len(grades)): # Получаем индексы от 0 до 4
    print('Студент №', str(i + 1) + ':', grades[i], 'баллов') # Выводим номер студента и его баллы

Выводим результат:

Студент №1: 95 баллов
Студент №2: 82 баллов
Студент №3: 74 баллов
Студент №4: 100 баллов
Студент №5: 89 баллов

Таким же способом можно изменять элементы списка в цикле:

numbers = [10, 20, 30]
for i in range(len(numbers)):
    numbers[i] = numbers[i] * 2
print(numbers) # [20, 40, 60]

С помощью range(len (numbers)) мы перебираем индексы от 0 до длины списка (в данном случае от 0 до 2). На каждой итерации обращаемся к элементу по его индексу i и присваиваем ему новое значение — исходное, умноженное на 2.

В цикле for можно работать с двумя списками одновременно:

names = ['Анна', 'Борис', 'Вика']
scores = [85, 90, 78]

for i in range(len(names)):
    print(names[i], '-', scores[i])

В примере выше мы используем общий индекс i для одновременного обращения к элементам обоих списков по их позициям — так мы можем связать имя каждого студента с его баллом. Посмотрите на результат:

Анна - 85
Борис - 90
Вика - 78

Как работать с float-значениями

Функция range() в Python работает только с целыми числами. Если вы попытаетесь передать ей дробное значение, то получите ошибку:

range(0.5, 5) # TypeError: 'float' object cannot be interpreted as an integer

Для работы с дробными значениями используйте библиотеку NumPy или цикл while. NumPy подходит для работы с массивами и сложных математических вычислений. Для простых задач, когда не хочется добавлять зависимости в проект, используйте while — он работает с дробными числами из коробки.

Рассмотрим пример с NumPy:

import numpy as np

for i in np.arange(0, 1, 0.2):
    print(i)

Результат:

0.0
0.2
0.4
0.6000000000000001
0.8

Здесь np.arange(start, stop, step) создаёт массив чисел с шагом 0.2, и цикл for перебирает их по порядку. Однако при работе с дробными числами может возникнуть проблема с точностью вычислений. Например, вместо 0.6 вы получите 0.6000000000000001 — это связано с особенностями представления чисел с плавающей точкой в памяти компьютера. Чтобы этого избежать, достаточно добавить функцию round() для округления после запятой:

import numpy as np
for i in np.arange(0, 1, 0.2):
    print(round(i, 1))  # Округляем до одного знака после запятой

Теперь результат будет чистым и понятным:

import numpy as np
for i in np.arange(0, 1, 0.2):
    print(round(i, 1))  # Округляем до одного знака после запятой

Попробуем цикл while и напишем код для вывода чисел от 0 до 0,8 с шагом 0,2:

i = 0.0
while i < 1.0:
    print(round(i, 1))
    i += 0.2

Результат совпадёт с тем, что даёт NumPy:

0.0
0.2
0.4
0.6
0.8

Здесь мы также добавили round(), чтобы избежать накопления ошибок округления, возникающих при многократном сложении дробных чисел.

Как проверить принадлежность к диапазону

Функция range() поддерживает оператор in — с его помощью можно выяснить, входит ли определённое значение в созданную последовательность. Например:

numbers = range(0, 10)

print(5 in numbers)   # True
print(15 in numbers)  # False

Здесь range(0, 10) создаёт числа от 0 до 9. Когда мы проверяем, входит ли число 5 в этот диапазон, Python возвращает True — оно действительно там есть. А число 15 выходит за пределы диапазона, поэтому результат False.

Оператор in можно использовать не только для проверки принадлежности, но и для фильтрации данных. Допустим, есть список чисел, и мы хотим выбрать только те значения, которые кратны 10 и входят в диапазон от 10 до 50:

values = [5, 10, 20, 25, 30, 45, 50, 60]
allowed = range(10, 51, 10)
for v in values:
    if v in allowed:
        print(v)

В данном примере мы создаём список значений values и диапазон allowed с числами, кратными 10. Цикл проходит по каждому значению из списка values — если оно входит в диапазон allowed, программа выводит его на экран. Оператор in позволяет быстро проверить принадлежность числа к range() без перебора всех элементов диапазона вручную. Числа из указанного диапазона:

10
20
30
50

Оператор in работает и при создании диапазона с отрицательным шагом — Python правильно определяет принадлежность числа к убывающей последовательности, проверяя не только границы, но и соответствие шагу:

r = range(10, 0, -2)
print(6 in r)  # True 
print(5 in r)  # False

Диапазон r состоит из таких чисел: 10, 8, 6, 4, 2. Число 6 входит в эту последовательность, поэтому проверка возвращает True. Число 5 тоже находится между 10 и 0, но не соответствует шагу −2 — поэтому результат False.

Как объединить диапазоны значений

Иногда нужно объединить результаты двух функций range(). Напрямую сложить два диапазона с помощью оператора + не получится — Python выдаст ошибку TypeError, поскольку объекты range не поддерживают операцию сложения. Однако объединить диапазоны всё же можно: для этого есть несколько способов, и далее мы рассмотрим два наиболее распространённых.

Самый простой вариант — превратить оба диапазона в списки и сложить их:

r1 = range(0, 5)
r2 = range(5, 10)

combined = list(r1) + list(r2)
print(combined) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Более эффективный способ — использовать модуль itertools. Функция itertools.chain() объединяет несколько последовательностей в один итерируемый объект, который можно обойти в цикле. Преимущество этого подхода в том, что он не создаёт промежуточные списки в памяти, элементы берутся по одному из каждого диапазона по мере необходимости, что значительно экономит ресурсы при работе с большими последовательностями:

from itertools import chain

r1 = range(0, 5)

r2 = range(5, 10)

for num in chain(r1, r2):
    print(num, end=' ') # 0 1 2 3 4 5 6 7 8 9

Как использовать range() в генераторах списков

Генератор списков — это конструкция в Python, которая позволяет создать новый список одной строкой без использования цикла for и метода append().

Обычный цикл для создания списка выглядит так:

numbers = []
for i in range(5):
    numbers.append(i ** 2)
print(numbers) # [0, 1, 4, 9, 16]

С помощью генератора списка тот же результат можно получить в одну строку:

numbers = [i ** 2 for i in range(5)]

print(numbers) # [0, 1, 4, 9, 16]

Синтаксис: [выражение for элемент in итерируемый_объект]. В примере:

  • выражение — i ** 2, где i — это элемент последовательности, которую мы создаём с помощью range();
  • элемент — i, переменная, которая принимает значения из последовательности;
  • итерируемый объект — последовательность, созданная функцией range(5).

Вы можете настроить функцию range() с любым шагом. Так, в примере ниже range(0, 10, 2) создаёт последовательность чётных чисел от 0 до 9 с шагом 2, а генератор списка затем собирает все отобранные значения в новый список:

evens = [i for i in range(0, 10, 2)]

print(evens) # [0, 2, 4, 6, 8]

Генераторы списков поддерживают условные выражения для фильтрации элементов. Например, чтобы отобрать нечётные числа, добавим условие
if i % 2! = 0 — оно проверяет, что остаток от деления на 2 не равен нулю:

odds = [i for i in range(10) if i % 2 != 0]

print(odds) # [1, 3, 5, 7, 9]

Больше интересного про код — в нашем телеграм-канале.  Подписывайтесь!



Python для всех

Вы освоите Python на практике и создадите проекты для портфолио — телеграм-бот, веб-парсер и сайт с нуля. А ещё получите готовый план выхода на удалёнку и фриланс. Спикер — руководитель отдела разработки в «Сбере».

Пройти бесплатно
Листая дальше, вы перейдете на страницу Python для всех: старт в IT с нуля



Бесплатный курс по разработке на Python ➞
Пройдите бесплатный курс по Python и создайте с нуля телеграм-бот, веб-парсер и сайт. Спикер — руководитель отдела разработки в «Сбере».
Пройти курс
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована