Содержание
- Введение в тему
- Range stop
- Range start stop step
- Функция python range с примерами
- Использование параметров start stop и step
- Использование отрицательных значений start stop и step
- Генерация диапазона как арифметический ряд
- Перебор списка с использованием range
- Преобразовать диапазон в список
- Верхний предел range включительно
- Использование индекса с результатом работы range python
- Объединить вывод двух функций range
- История range
- Инкрементация с range
- Декрементация с range
- Float и range
- Float
- Использование numpy
Введение в тему
Функция range в Python это одна из встроенных функций стандартной библиотеки. Она создаёт последовательность чисел типа int, от числа start до stop, с шагом step, указанными пользователем. Наиболее распространённое использование в циклах for.
Функция range() принимает обязательный и два необязательных параметра. В этом уроке мы Вы сможете изучить все возможности этой функции.
Range stop
Это главный способ использовать range(). Нужен всего один параметр для того чтобы задать верхнюю границу.
Последовательность чисел генерируется при таком варианте с нуля.
var = range(5)
for _ in var:
print(_)
# Вывод:
0
1
2
3
4
Range с нулём в качестве аргумента создаёт пустой диапазон.
var = range(0)
for _ in var:
print(_)
print(var)
# Вывод:
range(0, 0)
Range start stop step
Это немного более сложная форма range. Вы можете сгенерировать последовательность чисел более подробно задав необходимые параметры.
Для этого необходимо передать аргументы:
- start – От какого числа строить последовательность
- stop — До какого числа строить последовательность
- step — Шаг создания последовательности (по умолчанию равен 1)
Следует помнить:
- Нельзя устанавливать шаг равный нулю, иначе Вы получите ошибку ValueError.
- Значение, тип которого отличается от integer, вызывает TypeError.
- Ненулевое значение шага (> = stop) вернет диапазон, как минимум, состоящий из одного элемента.
Функция python range с примерами
Далее Вы можете увидеть листинги нескольких примеров.
Использование параметров start stop и step
for var in range(35, 39):
print(var)
print('='*5)
for var in range(35, 39, 10):
print(var)
# Вывод:
35
36
37
38
=====
35
Использование отрицательных значений start stop и step
Каждый параметр функции range может быть отрицательными. Отрицательный аргумент step означает что последовательность будет создана с конца:
for var in range(-22, -39, -3):
print(var, end=' ')
print('n', '='*10)
for var in range(39, 22, -3):
print(var, end=' ')
# Вывод:
-22 -25 -28 -31 -34 -37
==========
39 36 33 30 27 24
Генерация диапазона как арифметический ряд
Так же, при помощи функции range() можно создавать арифметические последовательности.
print(tuple(range(22, 39, 3)))
# Вывод:
(22, 25, 28, 31, 34, 37)
Объект, возвращаемый функцией range() работает как generator. В этом коде он преобразуется в кортеж, и теперь мы можем вывести на экран значения.
Перебор списка с использованием range
Функцию range() можно использовать для перебора коллекций. Однако, такой приём использовать не рекомендуется как не «Питоничный» — для этого в языке есть более удобные встроенные инструменты.
var = ['Ivan', 'Olga', 'Rinat', 'Kira']
collection_len = len(var)
for i in range(0, collection_len):
print(var[i])
# Вывод:
Ivan
Olga
Rinat
Kira
Преобразовать диапазон в список
Range() в Питон 3 создает объект сходный с генератором. При переборе значений range вычисляет их одно за другим, а не все сразу. Это называется ленивыми вычислениями и позволяет экономить задействованную память.
Результат вызова функции range() является immutable целочисленным набором. Это значит, что можно преобразовать то же самое в list, set или tuple Python.
import sys
var = range(0, 5)
print(type(var))
print('Используемая память -', sys.getsizeof(var), 'байт.')
for i in var:
print(var[i], end=' ')
var = tuple(var)
print('n', type(var))
print('Используемая память -', sys.getsizeof(var), 'байт.')
for i in var:
print(var[i], end=' ')
# Вывод:
<class 'range'>
Используемая память - 48 байт.
0 1 2 3 4
<class 'tuple'>
Используемая память - 80 байт.
0 1 2 3 4
Как Вы можете видеть, объект range занимает меньше памяти.
Верхний предел range включительно
По Python range() создаёт диапазон до значения, переданного как параметр stop, но само это значение не включает.
Однако можно добавить следующие изменения в код, чтобы изменить это поведение:
- Увеличьте значение stop используя счетчик шагов
- Передайте новое значение stop в функцию range()
start = 0 stop = 7 step = 1 for i in range(start, stop, step): print(i, end=" ") stop = stop + step print('n', end="") for i in range(start, stop, step): print(i, end=" ") # Вывод: 0 1 2 3 4 5 6 0 1 2 3 4 5 6 7
Использование индекса с результатом работы range python
Range() создаёт уникальный объект, обладающий свойствами, сходными с коллекциями и генераторами. Благодаря этому можно использовать срезы совместно с range.
var = range(10)
var = var[0:5]
print(var)
# Вывод:
range(0, 5)
Объединить вывод двух функций range
В Python объединить два объекта диапазона range() можно при помощи функции chain() из модуля itertools стандартной библиотеки.
from itertools import chain
var = chain(range(5), range(5, 10))
for _ in var:
print(_, end = " ")
# Вывод:
0 1 2 3 4 5 6 7 8 9
История range
Функция range в Python3 это переименованная функция xrange, взятая из Python2. Она отличается от функции range() из Python 2 тем что производит ленивые вычисления, то есть значения вычисляются по требованию, а не все сразу. Это сделано для оптимизации потребляемой памяти.
Подробнее можно изучить вопрос в PEP 3100.
Инкрементация с range
Для инкрементации необходимо использовать положительный шаг:
var = range(0, 50, 10)
for _ in var:
print(_, end = " ")
# Вывод:
0 10 20 30 40
В итоге цикл выдаёт коллекцию целых чисел, каждое из которых больше следующего на 10 (на заданный Вами шаг).
Декрементация с range
Для декрементации необходимо задать отрицательное приращение.
var = range(50, 0, -10)
for _ in var:
print(_, end = " ")
# Вывод:
50 40 30 20 10
В этом наборе чисел, каждое следующее меньше предшествующего на 10 (на заданный Вами шаг).
Ещё один способ сделать это – использовать встроенную функцию reversed().
var = range(0, 50, 10)
var = reversed(var)
for _ in var:
print(_, end = " ")
# Вывод:
40 30 20 10 0
Float и range
В функцию range можно передавать исключительно целые числа как значения параметров. Соответственно, последовательность, сгенерированная этой функцией, тоже состоит из значений, имеющих тип integer.
Float
Если передать в функцию в качестве аргументов десятичные числа, язык выдаст исключение.
var = range(0.0, 50, 10)
for _ in var:
print(_, end = " ")
# Вывод:
Traceback (most recent call last):
File "C:UsersDushenkoAppDataRoamingJetBrainsPyCharm2021.1scratchesscratch.py", line 1, in <module>
var = range(0.0, 50, 10)
TypeError: 'float' object cannot be interpreted as an integer
Если Вам необходим обходной путь, который позволит использовать действительные числа, Вам придётся использовать NumPy.
Использование numpy
NumPy – это сторонняя библиотека Python. Если вы собираетесь ее использовать, сначала вам нужно убедиться в том, что она установлена.
Для этого введите в REPL:
Если Вы получите ошибку ModuleNotFoundError, то вам нужно установить numpy. Чтобы сделать это, перейдите в командную строку и введите:
Теперь посмотрим, как это работает:
import numpy var = numpy.arange(0.3, 2, 0.3) for _ in var: print(_, end = " ") # Вывод: 0.3 0.6 0.8999999999999999 1.2 1.5 1.8
У компьютеров существуют проблемы с сохранением действительных чисел в двоичные числа с запятой. Итогом этих проблем является неверное отображение этих чисел.
Вы можете ознакомиться с библиотекой decimal, которая позволяет выражать вещественные числа в точном виде.
Так же можно использовать метод numpy.linspace(). Он производит сходные действия, но с использованием других аргументов. С numpy.linspace() вы определяете start и stop включительно, а также длину массива.
import numpy
var = numpy.linspace(3, 20, 3)
for _ in var:
print(_, end = " ")
# Вывод:
3.0 11.5 20.0
Встроенная функция Python под названием range может быть очень полезной, если вам нужно выполнить действие определенное количество раз.
К концу данного руководства вы будете:
- Понимать, как работает функция Python range;
- Знать, как отличаются реализации для Python 2 и Python 3;
- Увидите ряд наглядных примеров работы с range();
- Сможете работать с учетом ограничений range().
Содержание:
- История range()
- Циклы
- Введение в range()
- Инкрементация с range()
- Декрементация с range()
- Углубляемся в range()
- float и range()
- float
- Использование NumPy
- Итоги
Приступим к делу!
Несмотря на то, что range() в Python 2 и range() в Python 3 носят одинаковое название, они кардинально отличаются между собой. Фактически, range() в Python 3 – это просто переименованная версия функции под названием xrange в Python 2.
Есть вопросы по Python?
На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!
Telegram Чат & Канал
Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!
Паблик VK
Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!
Изначально, range() и xrange() приводили числа, которые можно повторить при помощи цикла for, однако первая функция генерировала список этих чисел, учитывая все за раз, в то время как вторая делала это более лениво, т. е. Числа возвращались по одному каждый раз, когда они нужны.
Наличие огромных списков занимает память, так что нет ничего удивительного в том, что xrange() заменила range(), ее имя и все остальное. Вы можете прочитать больше об этом решении и предыстории xrange() и range() в PEP 3100.
Обратите внимание: PEP означает Python Enhancement Proposal. Это документы, которые покрывают большое количество тем, включая недавно предоставленные новые функции, стили, философию и руководства.
Приступим!
Циклы
Перед тем, как мы ознакомимся с тем, как работает range(), нам нужно взглянуть на то, как работают циклы. Циклы — это ключевая концепция компьютерных наук. Если вы хотите стать хорошим программистом, умение обращаться с циклами — это важнейший навык, который стоит освоить.
Рассмотрим пример цикла for в Python:
captains = [‘Janeway’, ‘Picard’, ‘Sisko’] for captain in captains: print(captain) |
Выдача выглядит следующим образом:
Как вы видите, цикл for позволяет вам выполнять определенные части кода, столько раз, сколько вам угодно. В данном случае, мы зациклили список капитанов и вывели имена каждого из них.
Хотя Star Trek — отличная тема и все такое, вам может быть нужен более сложный цикл, чем список капитанов. Иногда вам нужно просто выполнить часть кода определенное количество раз. Циклы могут помочь вам с этим.
Попробуйте запустить следующий код с числами, кратными трем:
numbers_divisible_by_three = [3, 6, 9, 12, 15] for num in numbers_divisible_by_three: quotient = num / 3 print(f«{num} делится на 3, результат {int(quotient)}.») |
Выдача цикла будет выглядеть следующим образом:
3 делится на 3, результат 1. 6 делится на 3, результат 2. 9 делится на 3, результат 3. 12 делится на 3, результат 4. 15 делится на 3, результат 5. |
Это выдача, которая нам нужна, так что можем сказать, что цикл выполнил работу адекватно, однако есть еще один способ получения аналогично результата: использование range().
Обратите внимание: Последний пример кода содержит определенное форматирование строк. Чтобы узнать больше об этой теме, перейдите на статью F-Строки в новой версии Python.
Теперь, когда вы знакомы с циклами поближе, посмотрим, как вы можете использовать range() для упрощения жизни.
Введение в range()
Итак, как работает функция Python под названием range? Простыми словами, range() позволяет вам генерировать ряд чисел в рамках заданного диапазона. В зависимости от того, как много аргументов вы передаете функции, вы можете решить, где этот ряд чисел начнется и закончится, а также насколько велика разница будет между двумя числами.
Вот небольшой пример range() в действии:
for i in range(3, 16, 3): quotient = i / 3 print(f«{i} делится на 3, результат {int(quotient)}.») |
В этом цикле вы просто можете создать ряд чисел, кратных трем, так что вам не нужно вводить каждое из них лично.
Обратите внимание: хотя в этом примере показано надлежащее использование range(), его слишком часто приводят для использования в циклах.
Например, следующее использование range() едва ли можно назвать Питоническим (это плохой пример):
captains = [‘Janeway’, ‘Picard’, ‘Sisko’] for i in range(len(captains)): print(captains[i]) |
range() отлично подходит для создания повторяющихся чисел, но это не самый лучший выбор, если вам нужно перебрать данные, которые могут быть зациклены с помощью оператора in.
Есть три способа вызова range():
- range(стоп) берет один аргумент
- range(старт, стоп) берет два аргумента
- range(старт, стоп, шаг) берет три аргумента
Вызывая range() с одним аргументом, вы получите ряд чисел, начинающихся с 0 и включающих каждое число до, но не включая число, которое вы обозначили как конечное (стоп).
Как это выглядит на практике:
for i in range(3): print(i) |
Выдача вашего цикла будет выглядеть так:
Проверим: у нас есть все числа от 0 до, но не включая 3 — числа, которое вы указали как конечное.
range(старт, стоп)
Вызывая range() с двумя аргументами, вам нужно решить не только, где ряд чисел должен остановиться, но и где он должен начаться, так что вам не придется начинать с нуля каждый раз. Вы можете использовать range() для генерации ряда чисел, начиная с А до Б, используя диапазон (А, Б). Давайте узнаем, как генерировать диапазон, начинающийся с 1.
Попробуем вызывать range() с двумя аргументами:
for i in range(1, 8): print(i) |
Ваша выдача будет выглядеть следующим образом:
Отлично: у вас есть все числа от 1 (число, которые вы определили как стартовое), до, но не включая, 8 (число, которые вы определили как конечное).
Но если вы добавите еще один аргумент, то вы сможете воспроизвести ранее полученный результат, когда пользуетесь списком под названием numbers_divisible_by_three.
range(старт, стоп, шаг)
Вызывая range() с тремя аргументами, вы можете выбрать не только то, где ряд чисел начнется и остановится, но также то, на сколько велика будет разница между одним числом и следующим. Если вы не задаете этот «шаг», то range() автоматически будет вести себя так, как если бы шаг был бы равен 1.
Обратите внимание: шаг может быть положительным, или отрицательным числом, но он не может равняться нулю:
>>> range(1, 4, 0) Traceback (most recent call last): File «<stdin>», line 1, in <module> ValueError: range() arg 3 must not be zero |
Если вы попробуете использовать 0 как шаг, вы получите ошибку ValueError.
Теперь, так как вы знаете, как использовать шаг, вы можете снова использовать цикл, который мы видели ранее, с числами, кратными 3.
Попробуйте лично:
for i in range(3, 16, 3): quotient = i / 3 print(f«{i} делится на 3, результат {int(quotient)}.») |
Ваша выдача будет выглядеть абсолютно так же, как выдача для цикла for, которую мы видели ранее в данном руководстве, когда мы использовали список numbers_divisible_by_three:
3 делится на 3, результат 1. 6 делится на 3, результат 2. 9 делится на 3, результат 3. 12 делится на 3, результат 4. 15 делится на 3, результат 5. |
Как вы видите в этом примере, вы можете использовать аргумент шаг для увеличения в сторону больших чисел. Это называется инкрементация.
Инкрементация с range()
Если вы хотите выполнить инкрементацию, то вам нужно, чтобы шаг был положительным числом. Чтобы понять, что под этим имеется ввиду, введите следующий код:
for i in range(3, 100, 25): print(i) |
Если ваш шаг равен 25, то выдача вашего цикла будет выглядеть вот так:
Вы получили ряд чисел, каждое из которых больше предыдущего на 25, т.е., на заданный вами шаг.
Теперь, так как вы увидели то, как именно вы можете продвигаться вперед по диапазону, настало время узнать, как двигаться в обратную сторону.
Декрементация с range()
Если ваш шаг положительный — то вы двигаетесь по ряду увеличивающихся чисел, это называется инкрементация. Если ваш шаг отрицательный, то вы двигаетесь по ряду убывающих чисел, это называется декрементация. Это позволяет вам идти вспять.
В следующем примере ваш шаг будет -2. Это значит, что декрементация будет равна 2 для каждого цикла:
for i in range(10, —6, —2): print(i) |
Выдача вашего декременирующего цикла будет выглядеть следующим образом:
У вас есть ряд чисел, каждое из которое меньше предшествующего на 2, т. е., на абсолютное значение предоставленного вами шага.
Самый правильный способ создание диапазона декрементации, это использовать range(старт, стоп, шаг). При этом в Python есть встроенная обратная функция. Если вы завернете range() в reversed(), то вы сможете выводить целые числа в обратном порядке.
Давайте попробуем:
for i in reversed(range(5)): print(i) |
Вы получите следующее:
range() позволяет итерировать по декрементирующей последовательности чисел, где reversed() обычно используется для циклического преобразования последовательности в обратном порядке.
Обратите внимание: reversed() также работает со строками.
Углубляемся в range()
Теперь, когда вы ознакомились с основами использования range(), настало время спуститься немного глубже.
Как правило, range() используется в двух случаях:
- Выполнении тела цикла определенное количество раз;
- Создание более эффективных итераций целых чисел, которое может быть выполнено при помощи списков или кортежей.
Первое использование можно назвать самым простым, и вы можете сделать так, чтобы itertools дал вам более эффективный способ построения итераций, чем это может сделать range().
Вот еще несколько моментов, которые стоит учитывать при использовании range.
>>> type(range(3)) <class ‘range’> |
Вы можете получить доступ к объектам в range() по индексу, как если бы вы имели дело со списком:
print(range(3)[1]) # Результат: 1 print(range(3)[2]) # Результат: 2 |
Вы даже можете использовать срез в range(), но выдача в REPL может показаться немного странной, на первый взгляд:
print(range(6)[2:5]) # Результат: range(2, 5) |
Хотя эта выдача может выглядеть необычно, range() просто возвращает еще одну range().
Тот факт, что вы можете использовать элементы range() по индексу и фрагменту range() указывает на важный момент: range() весьма ленивый, в отличие от списка, но не является итератором.
float и range()
Вы могли обратить внимание на то, что все числа, с которыми мы имели дело, являлись целыми числами. Это связано с тем, что range() может принимать только целые числа в качестве аргументов.
float
В Python, если число не является целым, оно является десятичным. Есть несколько различий между целыми и десятичными числами.
Целое число (тип данных int):
- Является целым числом;
- Не содержит десятичной точки;
- Может быть положительным, отрицательными или нулем;
Десятичное число (тип данных float):
- Может быть любым числом, которое включает десятичную точку;
- Может быть положительным и отрицательным;
Попробуйте вызвать range() с десятичным числом и увидите, что будет:
for i in range(3.3): print(i) |
Вы увидите следующее уведомление об ошибке TypeError:
Traceback (most recent call last): File «<stdin>», line 1, in <module> TypeError: ‘float’ object cannot be interpreted as an integer |
Если вам нужен обходной путь, который позволит вам использовать десятичные числа, вы можете использовать NumPy.
Использование NumPy
NumPy – это сторонняя библиотека Python. Если вы собираетесь ее использовать, сначала вам нужно убедиться в том, что она установлена.
Как это сделать при помощи REPL:
Если вы получите ошибку ModuleNotFoundError, то вам нужно провести установку numpy. Чтобы сделать это, перейдите в командную строку и введите:
После установки, внесите следующее:
import numpy as np np.arange(0.3, 1.6, 0.3) |
Результат:
array([0.3, 0.6, 0.9, 1.2, 1.5]) |
Если вы хотите вывести каждое число на свою строку, вы можете сделать следующее:
import numpy as np for i in np.arange(0.3, 1.6, 0.3): print(i) |
Выдача будет следующей:
0.3 0.6 0.8999999999999999 1.2 1.5 |
Но откуда взялось число 0.8999999999999999?
У компьютеров есть проблемы с сохранением десятичных чисел с запятой в двоичные числа с запятой. Это приводит к разным неожиданным представлениям этих чисел.
Возможно, вы захотите взглянуть на библиотеку decimal, которая немного отстает в контексте производительности и читаемости, но позволяет вам выражать десятичные числа в точном виде.
Еще один вариант – использовать round(). Помните, что round() содержит собственные нюансы, которые могут приводить к неожиданным результатам!
Так или иначе, эти ошибки связанные с плавающей запятой являются проблемой, в зависимости от того, над какой задачей вы работаете. Ошибки могут быть выражены в виде, например, шестнадцатеричного десятичного числа, что не является критичной проблемой, в большинстве случаев. Они настолько маленькие, что, если вы только не работаете над расчетами орбитальной траектории спутников, вам не стоит беспокоиться.
В качестве альтернативы, вы можете использовать np.linspace(). Он делает в целом то же самое, но с использованием других параметров. С np.linspace() вы определяете начало и конец (оба включительно), а также длину и массив (за исключением шага).
Например, np.linspace(1, 4, 20) выдает 20 одинаково разделенных чисел: .0, …, 4.0. В другом случае, np.linspace(0, 0.5, 51) задает 0.00, 0.01, 0.02, 0.03, …, 0.49, 0.50.
Итоги
Теперь вы понимаете, как использовать range() и работать в обход его ограничений. Также вы понимаете, как эта важная функция развивалась между Python 2 и Python 3.
Счастливого программирования!
Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.
E-mail: vasile.buldumac@ati.utm.md
Образование
Universitatea Tehnică a Moldovei (utm.md)
- 2014 — 2018 Технический Университет Молдовы, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»
Числовой диапазон (range) — упорядоченная последовательность целых чисел с заданным шагом.
Синтаксис функции range выглядит так:
range([start], stop[, step])
start
— число начала последовательности (по умолчанию 0).
stop
— число конца последовательности.
step
— шаг между каждым числом последовательности.
Параметры start
и step
— не обязательные, если их не указывать, то последовательность будет создаваться от 0 до stop
с шагом 1.
Также следует помнить, что:
- Все параметры функции
range
должны быть целыми числами. - Параметры могут быть отрицательными числами.
- Если шаг
step
отрицательный, нужно помнить, что значениеstart
должно быть больше значенияstop
. - Параметр
stop
не включается в последовательность.
Для генерации будем использовать различные комбинации:
my_list = list(range(10)) print(my_list) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
my_list = list(range(5, 10)) print(my_list) #[5, 6, 7, 8, 9]
my_list = list(range(5, 10, 2)) print(my_list) #[5, 7, 9]
my_list = list(range(0, -10, -1)) print(my_list) #[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
Генерация списка в цикле с помощью range
nums = [n for n in range(1, 11)] print(nums) #[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Использование числового диапазона range в циклах
Несколько простых примеров:
for i in range(5): print(i) #0 #1 #2 #3 #4
for i in range(5, 10): print(i) #5 #6 #7 #8 #9
for i in range(2, 10, 2): print(i) #2 #4 #6 #8
Функция range для обратного порядка:
for i in range(-2, -10, -2): print(i) #-2 #-4 #-6 #-8
Индексация и срезы в range
Индексация range
Тут все стандартно, как и в списках и в кортежах, индексация начинается 0.
Обращение к элементу диапазона:
data = range(1, 10) print(data[0]) print(data[5]) print(data[-1]) #1 #6 #9
Срезы в range
Синтаксис срезов [I:J:Step]
.
С I
до смещения J
, не включая его.
data = range(1, 10) print(data[1:4]) print(data[:4]) print(data[3:]) #range(2, 5) #range(1, 5) #range(4, 10)
Основные операции с числовым диапазоном range
Длина диапазона: len(r)
data = range(10) print(len(data)) #10
Минимальный элемент диапазона: min(r)
data = range(10) print(min(data)) #0
Максимальный элемент диапазона: max(r)
data = range(10) print(max(data)) #9
Индекс числа в диапазоне: range.index(x[, start[, end]])
Необязательные аргументы start
и end
, указывают на промежуток поиска:
data = range(10) print(data.index(5)) #5
data = range(2, 10) print(data.index(5)) #3
Примеры работы range в задачах
Найти сумму чисел от 1 до 10.
Создадим переменную s
, в которую будем записывать сумму чисел. И присвоим ей значение 0.
Создадим числовой диапазон от 1 до 11 (т.к. range
не включает последнее число в последовательность)
Создадим цикл for
в котором будем перебирать в диапазоне цифры от 1 до 10.
Внутри цикла будем записывать в переменную s
сумму с каждым числом из диапазона.
s = 0 for i in range(1, 11): s = s + i print(s) #55
Найти сумму четных чисел от 1 до 10.
Делаем, все тоже самое, что и в первой задаче, но в range
делаем начало диапазона 0 и шаг 2, таким образом, получаем все четные числа от 0 до 10.
s = 0 for i in range(0, 11, 2): s = s + i print(s) #30
Вывести все буквы строки отдельно.
Создаем цикл длина диапазона, которого равна длине строки.
С помощью индексации выводим каждый элемент строки в цикле.
s = 'abcdef' for i in range(len(s)): print(s[i]) #a #b #c #d #e #f
Частая ошибка index out of range
Это ошибка возникает довольно часто, если не внимательно относиться к границам диапазона.
Допустим, есть список чисел от 1 до 10, нужно оставить в этом списке только числа, которые делятся на 2.
nums = [n for n in range(1, 11)] #генерируем список с числами о 1 до 10 for i in range(len(nums)): #перебераем все числа if nums[i] % 2 != 0: #находим числа, которые не делятся на 2 del nums[i] #удаляем такие числа print(nums) #builtins.IndexError: list assignment index out of range
В итоге вместо результата, получаем ошибку.
Это случилось из-за того, что мы прямо в цикле удалили элемент из списка, тем самым изменив его длину, а это повлияло на диапазон.
Т.е. на старте цикла была одна длина списка с числами, а во время выполнения эта длина изменилась. Python, держа в памяти старую длину, пробует обратиться по индексам к тем элементам, которых уже нет в списке.
Выход довольно прост, чтобы избежать такой ошибки, нельзя изменять список внутри цикла. Вместо этого лучше создавать новый список с нужным результатом.
nums = [n for n in range(1, 11)] #генерируем список с числами о 1 до 10 fin_nums = [] #создаем пустой список for i in range(len(nums)): #перебираем все числа if nums[i] % 2 == 0: #находим числа, которые делятся на 2 fin_nums.append(nums[i]) #добавляем в наш новый список print(fin_nums) #[2, 4, 6, 8, 10]
Теперь все гуд.
Содержание:развернуть
- Синтаксис
- for i in range
- Операции с range
- range и тип float
- Отличия между range в python2 и python3
- Best Practices
-
range в обратном порядке (python reverse range)
-
range включительно
-
range до бесконечности
-
range → в список (list) или множество (set)
Range — это встроенная функция Python, которая возвращает итерируемый объект (range object
), содержащий целые числа. С помощью функция range()
можно сгенерировать последовательность чисел с определенным шагом — далее их можно легко перебирать с помощью цикла for
.
В статье подробно рассказываю, как работает range()
, чем отличается её реализация в Python 2 и Python 3, а также приведу практические примеры использования.
Синтаксис
Функцию range()
можно использовать с одним или несколькими параметрами. В документации Python синтаксис выглядит следующим образом:
class range(stop) # с одним параметров
class range(start, stop[, step]) # с несколькими параметрами
У функции 3 параметра:
start
— начало последовательности [включительно] (не обязательный параметр, по умолчанию равен 0).stop
— задает точку остановки последовательности [значение не включено в последовательность] (обязательный параметр).step
— шаг последовательности (не обязательный параметр, по умолчанию равен 1).
Функция range()
возвращает объект класса range
:
print(type(range(3)))
> <class 'range'>
💁♂️ Примеры:
# от 0 до stop (не включая значение stop)
for i in range(7):
print(i, end=' ')
> 0 1 2 3 4 5 6
# от start до stop
for i in range(4, 11):
print(i, end=' ')
> 4 5 6 7 8 9 10
# от start до stop с шагом step
for i in range(4, 11, 2):
print(i, end=' ')
> 4 6 8 10
# последовательность в обратном порядке (не включая значение stop)
for i in range(10, 0, -1):
print(i, end=' ')
> 10 9 8 7 6 5 4 3 2 1
☝️ При работе с range()
важно помнить следующее:
- Значение
stop
не входит в последовательность; - Все аргументы функции должны быть целыми числами (положительными или отрицательными);
- При отрицательном шаге
step
нужно помнить, что значениеstart
должно быть больше значенияstop
; - Значение
step
не должно быть равно 0, иначе Python вызовет исключение «ValueError
«.
📃 Более подробное описание функции можно посмотреть в официальной документации или через help("range")
:
class range(object)
| range(stop) -> range object
| range(start, stop[, step]) -> range object
|
| Return an object that produces a sequence of integers from start (inclusive)
| to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.
| start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.
| These are exactly the valid indices for a list of 4 elements.
| When step is given, it specifies the increment (or decrement).
| ...
for i in range
Чаще всего range()
используется в циклах for.
Основной кейс — выполнение цикла N-раз:
for i in range(3):
print(f"iteration #{i + 1}")
> iteration #1
> iteration #2
> iteration #3
С помощью range()
можно перебрать все значения в последовательности:
str = 'abcdef'
for i in range(len(str)):
print(str[i], end=' ')
> a b c d e f
Или найти сумму первых 10-ти целых чисел.
s = 0
for i in range(11): # от 0 до 9 (11 не входит в последовательность)
s += i
print(s)
> 55
А так можно перебрать значения последовательности через одного:
s = 'a1b2c3d4e5f6g7h8'
for i in range(0, len(s), 2):
print(s[i], end=' ')
> a b c d e f g h
С помощью функции range()
можно организовать сдвиг букв в слове на одну позицию и получить все возможные варианты такого сдвига:
s = 'питон'
for i in range(len(s)):
s = s[1:] + s[:1]
print(s, end=' ')
> итонп тонпи онпит нпито питон
Или получить все числа из заданного диапазона, делящиеся на любое нужное. Например, напечатаем таблицу умножения на 8:
count = 1
for i in range(8, 80, 8):
print(count, ' * 8 = ', i)
count += 1
> 1 * 8 = 8
> 2 * 8 = 16
> 3 * 8 = 24
> 4 * 8 = 32
> 5 * 8 = 40
> 6 * 8 = 48
> 7 * 8 = 56
> 8 * 8 = 64
> 9 * 8 = 72
Операции с range
Объект range
поддерживает все операции, доступные последовательностям (кроме сложения и умножения):
>>> numbers = range(13)
>>> numbers[3] # обращение к конкретному элементу
3
>>> 3 in numbers # проверка на вхождение в диапазон
True
>>> numbers[:4] # срез диапазона
range(0, 4)
>>> len(numbers) # длина диапазона
13
>>> min(numbers) # минимальный элемент диапазона
0
>>> max(numbers) # максимальный элемент диапазона
12
>>> numbers = range(0, 13, 2)
>>> numbers.index(6) # индекс (позиция) числа в диапазоне
3
Также объект range можно привести к списку (list
) или множеству (set
):
>>> numbers = range(13)
>>> numbers_list = list(numbers)
>>> type(numbers_list)
<class 'list'>
>>> numbers_list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
>>> numbers_set = set(numbers)
>>> type(numbers_set)
<class 'set'>
>>> numbers_set
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
range и тип float
По умолчанию функция range()
позволяет использовать только целые числа в качестве параметров. Если вы передадите значение с плавающей точкой, то Python вызовет исключение TypeError
:
numbers = range(1.5)
print(numbers)
> Traceback (most recent call last):
File "test.py", line 1, in <module>
numbers = range(1.5)
TypeError: 'float' object cannot be interpreted as an integer
Чтобы сгенерировать последовательность из чисел с плавающей точкой, можно использовать стороннюю библиотеку NymPy
(её нужно предварительно установить). В ней есть функция arange()
, похожая на стандартную range()
:
import numpy as np
float_numbers = np.arange(4.6, 5.8, 0.3)
print(float_numbers)
> [4.6 4.9 5.2 5.5 5.8]
Если вы не хотите устанавливать библиотеку NymPy, то можно написать собственную функцию, например так:
def f_range(start, stop, step):
while start < stop:
yield round(float(start), 1)
start += step
print(list(f_range(4.6, 5.8, 0.3)))
> [4.6, 4.9, 5.2, 5.5, 5.8]
Отличия между range в python2 и python3
Range()
в Python2 и Python3 — это разные функции, которые отличаются друг от друга.
В Python2 функция range()
возвращает объект list
, то есть она выдает все числа сразу и помещает из в оперативную память. Поэтому, при генерации длинных последовательностей, увеличивается расход памяти и время работы.
Функция xrange()
в Python2 и range()
в Python3 не генерируют вся последовательность чисел сразу, а выдают нужные значения по мере необходимости, при переходе к следующей итерации цикла.
Таким образом, xrange()
используемая в Python2 и range()
в Python3 являются аналогами.
Best Practices
range в обратном порядке (python reverse range)
Получить последовательность в обратном порядке можно с помощью отрицательного аргумента step
:
reversed_range = range(5, 0, -1) # start = 5, stop = 0, step = -1
for i in reversed_range:
print(i, end=' ')
> 5 4 3 2 1
Обратите внимание, что start
> stop
, и stop
не входит в последовательность.
range включительно
По умолчанию, значение из переменной stop
не входит в последовательность. Чтобы это исправить, к stop
прибавьте step
:
step = 2
numbers = range(2, 10 + step, step)
for i in numbers:
print(i, end=' ')
> 2 4 6 8 10
range до бесконечности
Так как у функции range()
есть обязательный параметр stop
, бесконечный цикл сделать не получится.
Но это можно сделать через itertools
:
import itertools
import time
for i in itertools.count():
print(f"iter -> {i}")
time.sleep(1)
> iter -> 0
> iter -> 1
> iter -> 2
> ...
Или через бесконечный цикл while
:
import time
i = 0
while True:
print(f"iter -> {i}")
i += 1
time.sleep(1)
> iter -> 0
> iter -> 1
> iter -> 2
> ...
range → в список (list) или множество (set)
С помощью range
можно сгенерировать список (list
):
num_set = list(range(1, 11, 2)) # список целых чисел
print(num_set)
> [1, 3, 5, 7, 9]
Или сгенерировать множество (set
):
natural_num_set = set(range(1, 11)) # множество натуральных чисел от 1 до 10
print(natural_num_set)
> {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
Функция range()
генерирует последовательность целых чисел и обычно используется для организации перебора в циклах for
. При этом аргументами могут быть только целые числа, использование типов float, string и других недопустимо. Передаваемые значения могут быть как положительные, так и отрицательные, но step
не может быть равен нулю.
Встроенная функция Pythonrange
удобна, когда вам нужно выполнить действие определенное количество раз. Как опытный Pythonista, вы, скорее всего, использовали его раньше. Но что это делает?
К концу этого руководства вы:
-
Понять, как работает функция Python
range
-
Знать, как реализации отличаются в Python 2 и Python 3
-
Видел несколько практических примеров
range()
-
Быть оборудованным, чтобы обойти некоторые из его ограничений
Давайте взломать!
История функции Pythonrange()
Хотяrange()
в Python 2 иrange()
в Python 3 могут иметь одно и то же имя, это совершенно разные животные. Фактически,range()
в Python 3 — это просто переименованная версия функции, которая называетсяxrange
в Python 2.
Первоначально какrange()
, так иxrange()
выдавали числа, которые можно было повторять с помощью циклов for, но первые генерировали список этих чисел сразу, а вторые производили числаlazily, что означает номера возвращались по одному по мере необходимости.
Наличие огромных списков занимает много памяти, поэтому неудивительно, чтоxrange()
заменилrange()
, имя и все остальное. Вы можете узнать больше об этом решении и фонеxrange()
противrange()
вPEP 3100.
Note: PEP расшифровывается как Python Enhancement Proposal. PEP — это документы, которые могут охватывать широкий спектр тем, включая предлагаемые новые функции, стиль, управление и философию.
Естьa ton of them. PEP 1 объясняет, как они работают, и является отличным местом для начала.
В оставшейся части этой статьи вы будете использовать функцию, как она существует в Python 3.
Вот так!
Давай петля
Прежде чем мы углубимся в то, как работаетrange()
, нам нужно взглянуть на то, как работает цикл. Цикл — этоkey computer science concept. Если вы хотите быть хорошим программистом, освоение циклов является одним из первых шагов, которые вам нужно сделать.
Вот пример цикла for в Python:
captains = ['Janeway', 'Picard', 'Sisko']
for captain in captains:
print(captain)
Вывод выглядит так:
Как вы можете видеть, цикл for позволяет вам выполнять определенный блок кода сколько угодно раз. В этом случае мы просмотрели список капитанов и напечатали каждое из их имен.
Хотя Star Trek великолепен и все такое, вы можете захотеть сделать больше, чем просто просмотреть список капитанов. Иногда вы просто хотите выполнить блок кода определенное количество раз. Петли могут помочь вам сделать это!
Попробуйте следующий код с числами, которые делятся на три:
numbers_divisible_by_three = [3, 6, 9, 12, 15]
for num in numbers_divisible_by_three:
quotient = num / 3
print(f"{num} divided by 3 is {int(quotient)}.")
Вывод этого цикла будет выглядеть так:
3 divided by 3 is 1. 6 divided by 3 is 2. 9 divided by 3 is 3. 12 divided by 3 is 4. 15 divided by 3 is 5.
Это именно тот результат, который нам нужен, чтобы цикл выполнил свою работу надлежащим образом, но есть другой способ получить тот же результат, используяrange()
.
Теперь, когда вы более знакомы с циклами, давайте посмотрим, как вы можете использоватьrange()
, чтобы упростить себе жизнь.
Основы Pythonrange()
Так как же работает функция Pythonrange
? Проще говоря,range()
позволяет генерировать серию чисел в заданном диапазоне. В зависимости от того, сколько аргументов вы передаете в функцию, вы можете решить, где эта серия чисел будет начинаться и заканчиваться, а также насколько велика будет разница между одним числом и следующим.
Вот краткий обзорrange()
в действии:
for i in range(3, 16, 3):
quotient = i / 3
print(f"{i} divided by 3 is {int(quotient)}.")
В этом цикле for вы могли просто создать диапазон чисел, которые делятся на3
, поэтому вам не нужно было указывать каждое из них самостоятельно.
Note: Хотя в этом примере показано правильное использованиеrange()
, обычно не одобряется слишком частое использованиеrange()
в циклах for.
Например, следующее использованиеrange()
обычно считается не Pythonic:
captains = ['Janeway', 'Picard', 'Sisko']
for i in range(len(captains)):
print(captains[i])
range()
отлично подходит для создания итераций чисел, но это не лучший выбор, когда вам нужно перебирать данные, которые можно перебрать с помощьюin
operator.
Вы можете вызватьrange()
тремя способами:
-
range(stop)
принимает один аргумент. -
range(start, stop)
принимает два аргумента. -
range(start, stop, step)
принимает три аргумента.
range(stop)
Когда вы вызываетеrange()
с одним аргументом, вы получите серию чисел, которая начинается с0
и включает все целые числа до, но не включая, числа, которое вы указали какstop
с.
Вот как это выглядит на практике:
for i in range(3):
print(i)
Вывод вашего цикла будет выглядеть так:
Это подтверждается: у нас есть все целые числа от0
до3
, но не включая его, число, которое вы указали какstop
.
range(start, stop)
Когда вы вызываетеrange()
с двумя аргументами, вы можете решить не только, где заканчивается последовательность чисел, но и где она начинается, поэтому вам не нужно начинать с0
все время. Вы можете использоватьrange()
для генерации ряда чисел отA доB, используяrange(A, B)
. Давайте узнаем, как создать диапазон, начинающийся с1
.
Попробуйте вызватьrange()
с двумя аргументами:
for i in range(1, 8):
print(i)
Ваш вывод будет выглядеть так:
Пока все хорошо: у вас есть все целые числа от1
(число, указанное вами какstart
) до, но не включая8
(число, указанное вами какstop
с).
Но если вы добавите еще один аргумент, вы сможете воспроизвести результат, который вы получили ранее, когда использовали список с именемnumbers_divisible_by_three
.
range(start, stop, step)
Когда вы вызываетеrange()
с тремя аргументами, вы можете выбрать не только, где последовательность чисел будет начинаться и останавливаться, но также насколько велика будет разница между одним числом и другим. Если вы не укажетеstep
, тоrange()
будет автоматически вести себя так, как если быstep
был1
.
Note:step
может быть положительным или отрицательным числом, но не0
:
>>>
>>> range(1, 4, 0)
Traceback (most recent call last):
File "", line 1, in
ValueError: range() arg 3 must not be zero
Если вы попытаетесь использовать0
в качестве шага, вы получите сообщение об ошибке.
Теперь, когда вы знаете, как использоватьstep
, вы можете, наконец, вернуться к тому циклу, который мы видели ранее, с делением на3
.
Попробуйте сами:
for i in range(3, 16, 3):
quotient = i / 3
print(f"{i} divided by 3 is {int(quotient)}.")
Ваш вывод будет выглядеть точно так же, как вывод цикла for, который вы видели ранее в этой статье, когда вы использовали список с именемnumbers_divisible_by_three
:
3 divided by 3 is 1. 6 divided by 3 is 2. 9 divided by 3 is 3. 12 divided by 3 is 4. 15 divided by 3 is 5.
Как вы видите в этом примере, вы можете использовать аргументstep
для увеличения в сторону большего числа. Это называется приращением.
Приращение сrange()
Если вы хотите увеличить, вам нужно, чтобыstep
было положительным числом. Чтобы понять, что это означает на практике, введите следующий код:
for i in range(3, 100, 25):
print(i)
Если вашstep
равен25
, то результат вашего цикла будет выглядеть так:
У вас есть диапазон чисел, каждое из которых больше предыдущего на25
, указанное вамиstep
.
Теперь, когда вы увидели, как вы можете шагать вперед через диапазон, пришло время посмотреть, как вы можете сделать шаг назад.
Уменьшение сrange()
Если вашstep
положительный, то вы перемещаетесь по серии увеличивающихся чисел и увеличиваете их. Если вашstep
отрицательный, вы перемещаетесь через серию убывающих чисел и убываете. Это позволяет вам проходить номера в обратном направлении.
В следующем примере вашstep
равен-2
. Это означает, что вы будете уменьшать на2
для каждого цикла:
for i in range(10, -6, -2):
print(i)
Вывод вашего декрементного цикла будет выглядеть так:
У вас есть диапазон чисел, каждое из которых меньше предыдущего на2
,absolute value изstep
, которое вы указали.
Самый питонический способ создать уменьшающийся диапазон — использоватьrange(start, stop, step)
. Но в Python есть встроенная функцияreversed
. Если вы заключитеrange()
внутрьreversed()
, вы можете вывести целые числа в обратном порядке.
Попробуйте это:
for i in reversed(range(5)):
print(i)
Вы получите это:
range()
позволяет перебирать убывающую последовательность чисел, тогда какreversed()
обычно используется для перебора последовательности в обратном порядке.
Note:reversed()
также работает со строками. Вы можете узнать больше о функциональностиreversed()
со строками вHow to Reverse a String in Python.
Расширенные примеры использования функции Pythonrange()
Теперь, когда вы знаете основы использованияrange()
, пора копнуть глубже.
range()
в основном используется для двух целей:
-
Выполнение тела цикла for определенное количество раз
-
Создание более эффективных итераций целых чисел, чем можно сделать с помощьюlists or tuples
Первое использование, вероятно, является наиболее распространенным, и вы можете указать, чтоitertools дает вам более эффективный способ создания итераций, чемrange()
.
Вот еще несколько моментов, которые следует учитывать при использовании диапазона.
range()
— это тип в Python:
>>>
Вы можете получить доступ к элементам вrange()
по индексу, как и со списком:
>>>
>>> range(3)[1]
1
>>> range(3)[2]
2
Вы даже можете использовать нотацию срезов вrange()
, но вывод в REPL сначала может показаться немного странным:
>>>
>>> range(6)[2:5]
range(2, 5)
Хотя этот вывод может выглядеть странно, нарезкаrange()
просто возвращает другойrange()
.
Тот факт, что вы можете получить доступ к элементамrange()
по индексу и разрезатьrange()
, подчеркивает важный факт:range()
ленив, в отличие от списка, ноisn’t an iterator.
Плавающие иrange()
Возможно, вы заметили, что все числа, с которыми мы имели дело, были целыми числами, которые также называются целыми числами. Это потому, чтоrange()
может принимать только целые числа в качестве аргументов.
Слово на поплавках
В Python, если число не является целым числом, это число с плавающей точкой. Есть некоторые различия между целыми числами и числами с плавающей точкой.
Целое число (тип данныхint
):
-
Целое число
-
Не включает десятичную точку
-
Может быть положительным, отрицательным или
0
Число с плавающей запятой (тип данныхfloat
):
-
Может быть любым числом с десятичной точкой
-
Может быть положительным или отрицательным
Попробуйте вызватьrange()
с плавающей точкой и посмотрите, что произойдет:
for i in range(3.3):
print(i)
Вы должны получить следующее сообщение об ошибке:
Traceback (most recent call last):
File "", line 1, in
TypeError: 'float' object cannot be interpreted as an integer
Если вам нужно найти обходной путь, который позволит вам использовать поплавки, то вы можете использовать NumPy.
Использованиеrange()
с NumPy
NumPy — это сторонняя библиотека Python. Если вы собираетесь использовать NumPy, первым делом проверьте, установлена ли она у вас.
Вот как вы можете сделать это в своем REPL:
>>>
Если вы получилиModuleNotFoundError
, то вам необходимо его установить. Для этого перейдите в командную строку и введитеpip install numpy
.
После того, как он установлен, введите следующее:
import numpy as np
np.arange(0.3, 1.6, 0.3)
Это вернет это:
array([0.3, 0.6, 0.9, 1.2, 1.5])
Если вы хотите напечатать каждое число в отдельной строке, вы можете сделать следующее:
import numpy as np
for i in np.arange(0.3, 1.6, 0.3):
print(i)
Это вывод:
0.3 0.6 0.8999999999999999 1.2 1.5
Откуда взялся0.8999999999999999
?
У компьютеров возникают проблемы с сохранением десятичных чисел с плавающей точкой в двоичных числах с плавающей точкой. Это приводит к всевозможным неожиданным представлениям чисел.
Note: Чтобы узнать больше о том, почему возникают проблемы с десятичными знаками, вы можете проверитьthis article иPython docs.
Возможно, вы также захотите взглянуть наdecimal library, что немного снижает производительность и удобочитаемость, но позволяет точно представлять десятичные числа.
Другой вариант — использоватьround()
, о котором вы можете узнать больше вHow to Round Numbers in Python. Имейте в виду, чтоround()
имеет свои особенности, которые могут привести к неожиданным результатам!
Являются ли эти ошибки с плавающей запятой проблемой для вас, зависит от проблемы, которую вы решаете. Ошибки будут в чем-то вроде 16-го знака после запятой, который в большинстве случаев незначителен. Они настолько малы, что, если вы не работаете над расчетом спутниковых орбитальных траекторий или чего-то подобного, вам не нужно об этом беспокоиться.
В качестве альтернативы вы также можете использоватьnp.linspace()
. По сути, он делает то же самое, но использует разные параметры. С помощьюnp.linspace()
вы указываетеstart
иend
(оба включительно), а также длину массива (вместоstep
).
Например,np.linspace(1, 4, 20)
дает 20 чисел с равным интервалом:1.0, ..., 4.0
. С другой стороны,np.linspace(0, 0.5, 51)
дает0.00, 0.01, 0.02, 0.03, ..., 0.49, 0.50
.
Иди дальше и петля
Теперь вы понимаете, как использоватьrange()
и как обходить его ограничения. У вас также есть представление о том, как эта важная функция развивалась между Python 2 и Python 3.
В следующий раз, когда вам нужно будет выполнить действие определенное количество раз, у вас будет все готово, чтобы замолчать!
Счастливого Pythoning!