Python: разница между range и xrange
В программировании на Python у нас есть две функции range() и xrange(), которые генерируют целые числа из заданного начального и конечного значений. Здесь мы обсуждаем основные различия между функциями xrange и range.
Что такое range и xrange?
В Python 2.x у нас было два основных метода для генерации списка целых чисел в заданном диапазоне.
Однако в Python 3 xrange() переименован в range().
Следовательно, в Python 3 мы получаем единственную функцию, которая может производить числа из заданного диапазона.
Функция range() в python 3.x — это просто повторная реализация xrange() в python 2.x и она на самом деле работает так же, как xrange.
Если вы используете Python 2.x, тогда разница между xrange() и range () значима для вас.
В чем же была разница в Python 2.x
Две функции диапазона имеют много разных черт. Они могут относиться к производительности, потреблению памяти, скорости и внутреннему дизайну. Каждый из них имеет свою реализацию. Теперь давайте рассмотрим каждое из этих отличий по одному.
Операционная разница
В большинстве случаев и xrange, и range работают одинаково. Они оба дают возможность составить список чисел.
Следовательно, мы можем сказать, что оба схожи с точки зрения функциональности. Давайте сейчас посмотрим несколько примеров:
Выражение range(1, 7, 2) даст результат [1, 3, 5], а xrange(1, 7, 2) — [1, 3, 5]. Следовательно, вы можете сделать вывод, что они имеют сходную схему исполнения и выходные данные.
Возвращаемые значения и тип
Это основной источник различий между функциями xrange и range.
Range() возвращает объект типа list. Например, выражение range(1, 100, 1) создаст диапазон чисел от 0 до 99 и вернет все цифры за один раз.
>>> r = range(1, 100, 1) >>> type(r) >>> len(r) 99
С другой стороны, xrange() предоставляет результаты в виде объекта xrange. Он выполняет ленивую оценку. Он сохраняет аргументы и возвращает числа по запросу. В отличие от range(), он позволяет избежать получения всех чисел за один раз.
Объект xrange допускает итерацию, индексацию и метод len(). Вы можете использовать его в цикле for, чтобы обойти и получать числа в каждой итерации.
>>> xr = xrange(1, 100, 1) >>> type(xr) >>> xr[0] 1 >>> for it in xr: . print(it) . 1 2 3 . 99
Python xrange vs. range — кто быстрее?
У нас есть модуль timeit в Python для захвата времени выполнения любой функции. Мы будем использовать его в нашем тесте и посмотрим, какой из них быстрее.
Мы выполнили range() в нашем тесте три раза, в пример ниже приведен результат и время, которое потребовалось для выполнения:
>>> import timeit >>> timeit.timeit('"-".join(str(num) for num in range(10000))', number=10000) 22.56510010000011 >>> timeit.timeit('"-".join(str(num) for num in range(10000))', number=10000) 22.796818399999893 >>> timeit.timeit('"-".join(str(num) for num in range(10000))', number=10000) 24.003325399999994
Мы снова провели один и тот же тест с xrange() три раза и записали время их выполнения.
>>> timeit.timeit('"-".join(str(num) for num in xrange(10000))', number=10000) 20.672853799999984 >>> timeit.timeit('"-".join(str(num) for num in xrange(10000))', number=10000) 20.471903500000053 >>> timeit.timeit('"-".join(str(num) for num in xrange(10000))', number=10000) 20.15995029999999
Из приведенных выше тестов и результатов вы можете оценить, что xrange быстрее, чем стандартная функция диапазона.
- При использовании xrange вы могли заметить, что он не создает статический список, как функция range(). Вместо этого он больше похож на генератор, который выдает значения по запросу.
- Функция range() получает все числа сразу перед выполнением любой инструкции в цикле.
Вот некоторые факты для вашей справки:
- Основная проблема со стандартной функцией range() заключается в том, что она потребляет значительный объем памяти, особенно для большего диапазона чисел.
- Функция xrange() всегда предоставляет следующий элемент по запросу. Это означает, что в памяти одновременно существует только один элемент. Следовательно, он потребляет меньше памяти.
Что предпочесть range или xrange?
Это компромисс между мгновенным результатом и сегментированным выходом. С помощью xrange мы получаем более быстрый ответ; Кроме того, он потребляет меньше памяти.
Следовательно, очевидно, что Python xrange имеет преимущество над традиционной функцией range(). Давайте теперь посмотрим на некоторые случаи, чтобы понять, какой из этих методов подходит и где.
Где предпочтительно использовать xrange()?
- Когда диапазон имеет более широкий охват, мы рекомендуем использовать xrange(). Это улучшит скорость и потребует меньше памяти.
- Если вы планируете работать на маломощных устройствах (которые имеют ограничения памяти), тогда с xrange() вы можете не увидеть проблем с буфером.
Где предпочтительно использовать range()?
- Когда вам приходится часто просматривать список, лучше использовать range(). С xrange() было бы непросто создать экземпляр целочисленного объекта для каждого запроса на индексирование.
- Если вы используете небольшой диапазон, то использование функции range() — правильная идея.
- Так как метод range возвращает объект списка, вы можете использовать все его функции. Напротив, xrange предоставляет голый целочисленный объект, который требует индексации.
- Интересно, что если вы хотите, чтобы ваш код Python 2.x был совместим с версией 3.x, вам также следует использовать метод range.
Совместимость Между Python И Xrange
В Python 3.x функция xrange не существует, тогда как она предоставляет функцию range(). Реальность такова, что название «xrange» изменилось на «range» в Python 3.x.
Таким образом, если вы выполните вызов xrange() в Python 3.x, это вызовет приведенную ниже ошибку.
NameError: name ‘xrange’ is not defined
Кроме того, если вы решите импортировать xrange, даже тогда произойдет следующая ошибка.
ImportError: No module named ‘xrange’
Следовательно, вы можете решить использовать range() вместо xrange() для обеспечения совместимости между различными версиями.
Функция xrange() в Python
Функция xrange() в Python используется для генерации последовательности целых чисел. Эта функция является частью Python 2. В Python 3 имя было изменено на функцию range().
Синтаксис xrange()
xrange(start, end, step)
- Переменная start определяет начальный номер, он входит в выходную последовательность целых чисел. Это необязательно, значение по умолчанию – 0.
- Конечная переменная определяет конечное число, оно исключается из выходной последовательности целых чисел. Обязательный параметр.
- Шаг определяет разницу между каждым числом в последовательности. Это необязательно со значением по умолчанию 1.
- Когда передается только один аргумент, он рассматривается как конечная переменная.
Примеры функции
Давайте посмотрим на несколько примеров использования функции xrange() с помощью Python Interpreter.
1. Только с конечной переменной
>>> x = xrange(5) >>> print(type(x)) >>> >>> for n in x: . print(n) . 0 1 2 3 4 >>>
2. Сначальным и конечным значениями
>>> x = xrange(3, 6) >>> for n in x: . print(n) . 3 4 5 >>>
3. С переменными start, end и step
>>> x = xrange(3, 10, 2) >>> for n in x: . print(n) . 3 5 7 9 >>>
Сравнение функций range() и xrange()
Если вы используете версию Python 2.x, используйте функцию xrange() для генерации последовательности чисел. Если вы используете Python 3, используйте функцию range(), поскольку xrange() был переименован в функцию range().
4.3. Функции range() и xrange()
Если Вам необходимо перебирать последовательность чисел, то пригодится встроенная функция range() . Она создает список, содержащий арифметическую прогрессию:
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Указанная верхняя граница никогда не входит в созданную последовательность. range(10) создает список из 10 значений, точно соответствующих допустимым индексам для элементов последовательности, имеющей длину 10. Можно указать другую нижнюю границу или другое приращение (шаг), в том числе и отрицательное:
>>> range(5, 10)
[5, 6, 7, 8, 9]
>>> range(0, 10, 3)
[0, 3, 6, 9]
>>> range(-10, -100, -30)
[-10, -40, -70]
Для того, чтобы перебрать индексы последовательности, используйте совместно range() и len() :
>>> a = [‘У’, ‘Матери’, ‘есть’, ‘маленькая’, ‘овечка’]
>>> for i in range(len(a)):
. print i, a[i]
.
0 У
1 Матери
2 есть
3 маленькая
4 овечка
Дотошный читатель может заметить, что если нужно перебирать числа большого диапазона, создание списка будет неоправданно, а в некоторых случаях просто не хватит памяти:
>>> l=range(1000000000)
Traceback (most recent call last):
File «», line 1, in
MemoryError
Действительно, если мы не собираемся изменять список, достаточно создать псевдосписок — объект, для которого мы можем получить значения «элементов», но не можем изменить их или порядок их следования. Для этих целей в языке Python предусмотрена функция xrange() :
>>> xrange(5, 10)
xrange(5, 10)
>>> xrange(0, 10, 3)
xrange(0, 12, 3)
>>> xrange(-10, -100, -30)
xrange(-10, -100, -30)
>>> a = [‘У’, ‘Матери’, ‘есть’, ‘маленькая’, ‘овечка’]
>>> for i in xrange(len(a)):
. print i, a[i]
.
0 У
1 Матери
2 есть
3 маленькая
4 овечка
- (в том числе и инструкция for) требует возможности получить произвольный элемент по индексу.
Функция range в Python
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 :
# от 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 #») > 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) >>> numbers_list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] >>> numbers_set = set(numbers) >>> type(numbers_set) >>> numbers_set
range и тип float
По умолчанию функция range() позволяет использовать только целые числа в качестве параметров. Если вы передадите значение с плавающей точкой, то Python вызовет исключение TypeError :
numbers = range(1.5) print(numbers) > Traceback (most recent call last): File «test.py», line 1, in 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, то можно написать собственную функцию, например так:
Отличия между 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 -> «) time.sleep(1) > iter -> 0 > iter -> 1 > iter -> 2 > .
Или через бесконечный цикл while :
import time i = 0 while True: print(f»iter -> «) 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) >
Функция range() генерирует последовательность целых чисел и обычно используется для организации перебора в циклах for . При этом аргументами могут быть только целые числа, использование типов float, string и других недопустимо. Передаваемые значения могут быть как положительные, так и отрицательные, но step не может быть равен нулю.