По-видимому, xrange быстрее, но я понятия не имею, почему это быстрее (и нет доказательств, кроме анекдотических до сих пор, что это быстрее) или что помимо этого отличается
for i in range(0, 20):
for i in xrange(0, 20):
По-видимому, xrange быстрее, но я понятия не имею, почему это быстрее (и нет доказательств, кроме анекдотических до сих пор, что это быстрее) или что помимо этого отличается
for i in range(0, 20):
for i in xrange(0, 20):
В Python 2.x:
range
создает список, поэтому, если вы сделаете range(1, 10000000)
, он создаст список в памяти с элементами 9999999
.
xrange
является объектом последовательности, который оценивает лениво.
В Python 3 range
делает эквивалент Python xrange
, и чтобы получить список, вы должны использовать list(range(...))
.
диапазон создает список, поэтому, если вы делаете
range(1, 10000000)
он создает список в памяти с9999999
элементами.
xrange
- это генератор, поэтому онпредставляет собой объект последовательности,который оценивается лениво.
Это верно, но в Python 3, .range()
будет реализован Python 2. .xrange()
. Если вам нужно создать список, вам нужно будет:
list(range(1,100))
Помните, используйте модуль timeit
для проверки того, какой из небольших фрагментов кода работает быстрее!
$ python -m timeit 'for i in range(1000000):' ' pass'
10 loops, best of 3: 90.5 msec per loop
$ python -m timeit 'for i in xrange(1000000):' ' pass'
10 loops, best of 3: 51.1 msec per loop
Лично я всегда использую .range()
, если только не имею дело с действительно огромными списками - как вы можете видеть, по времени, для списка из миллиона записей, дополнительные накладные расходы составляют всего 0,04 секунды. И, как указывает Кори, в Python 3.0 .xrange()
исчезнет, и .range()
даст вам хорошее поведение итератора в любом случае.
xrange
сохраняет только параметры диапазона и генерирует числа по требованию. Однако реализация C в Python в настоящее время ограничивает свои аргументы на C longs:
xrange(2**32-1, 2**32+1) # When long is 32 bits, OverflowError: Python int too large to convert to C long
range(2**32-1, 2**32+1) # OK --> [4294967295L, 4294967296L]
Обратите внимание, что в Python 3.0 существует только range
, и он ведет себя как 2.x xrange
, но без ограничений на минимальные и максимальные конечные точки.
xrange возвращает итератор и сохраняет только один номер в памяти за раз. диапазон сохраняет весь список номеров в памяти.
Проведите некоторое время с Справочник по библиотеке. Чем более вы знакомы с ним, тем быстрее вы сможете найти ответы на такие вопросы. Особенно важны первые несколько глав о встроенных объектах и типах.
Преимущество типа xrange заключается в том, что объект xrange всегда будет взять тот же объем памяти, независимо от размера диапазона, который он представляет. Не существует согласованных преимуществ производительности.
Другим способом поиска быстрой информации о конструкции Python является docstring и help-function:
print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)
range() vs xrange() в python:
range() и xrange() - это две функции, которые могут использоваться для повторения определенного количества раз для циклов в Python. В Python 3 отсутствует xrange, но функция диапазона ведет себя как xrange в Python 2. Если вы хотите написать код, который будет работать как на Python 2, так и на Python 3, вы должны использовать range().
range() - возвращает список номеров, созданных с использованием функции range().
xrange() - эта функция возвращает объект-генератор, который может использоваться для отображения чисел только путем циклирования. Только конкретный диапазон отображается по запросу и, следовательно, называется "ленивая оценка".
Оба они реализованы по-разному и имеют разные характеристики, связанные с ними. Точками сравнения являются:
1. Тип возврата:
range() возвращает - список как возвращаемый тип.
xrange() возвращает - объект xrange().
# initializing a with range()
a = range(1,10000)
# initializing a with xrange()
x = xrange(1,10000)
# testing the type of a
print ("The return type of range() is : ")
print (type(a))
# testing the type of x
print ("The return type of xrange() is : ")
print (type(x))
Выход :
The return type of range() is :
<type 'list'>
The return type of xrange() is :
<type 'xrange'>
2. Память:
Переменная, сохраняющая диапазон, созданный диапазоном(), занимает больше памяти по сравнению с переменной, сохраняющей диапазон, используя xrange(). Основной причиной этого является тип возвращаемого значения range() - list и xrange() - объект xrange().
# initializing a with range()
a = range(1,10000)
# initializing a with xrange()
x = xrange(1,10000)
# testing the size of a
print ("The size allotted using range() is : ")
print (sys.getsizeof(a))
# testing the size of a
print ("The size allotted using xrange() is : ")
print (sys.getsizeof(x))
Выход :
The size allotted using range() is :
80064
The size allotted using xrange() is :
40
3. Использование операций:
Когда range() возвращает список, все операции, которые могут быть применены в списке, могут быть использованы на нем. С другой стороны, поскольку xrange() возвращает объект xrange, операции, связанные с списком, не могут быть применены к ним, что является недостатком.
# Python code to demonstrate range() vs xrange()
# on basis of operations usage
# initializing a with range()
a = range(1,6)
# initializing a with xrange()
x = xrange(1,6)
# testing usage of slice operation on range()
print ("The list after slicing using range is : ")
print (a[2:5])
# testing usage of slice operation on xrange()
print ("The list after slicing using xrange is : ")
print (x[2:5])
Выход :
The list after slicing using range is :
[3, 4, 5]
The list after slicing using xrange is :
Traceback (most recent call last):
File "pp.py", line 18, in <module>
print (x[2:5])
TypeError: sequence index must be integer, not 'slice'
4. Скорость:
Из-за того, что xrange() оценивает только объект-генератор, содержащий только те значения, которые требуются ленивой оценкой, поэтому быстрее в реализации, чем range().
Важные моменты :
Диапазонсоздает список, поэтому, если вы делаете диапазон (1, 10000000), он создает список в памяти с 10000000 элементами. xrange - это генератор, поэтому он лениво оценивает.
Это дает вам два преимущества:
MemoryError
.Я шокирован, никто не читает doc:
Эта функция очень похожа на
range()
, но возвращает объектxrange
вместо списка. Это непрозрачный тип последовательности, который дает те же значения, что и соответствующий список, без фактического их одновременного хранения. Преимуществоxrange()
overrange()
минимально (посколькуxrange()
по-прежнему нужно создавать значения, когда их спрашивают), за исключением случаев, когда очень сильно используется диапазон на машине с голодающей памятью или когда все элементы диапазона никогда не используется (например, когда цикл обычно заканчивается с помощьюbreak
).
Это по соображениям оптимизации.
range() создаст список значений от начала до конца (0.. 20 в вашем примере). Это станет дорогостоящей операцией на очень больших диапазонах.
xrange(), с другой стороны, намного оптимизирован. он будет вычислять только следующее значение при необходимости (через объект последовательности xrange) и не создает список всех значений, таких как range().
В этом простом примере вы найдете преимущество xrange
over range
:
import timeit
t1 = timeit.default_timer()
a = 0
for i in xrange(1, 100000000):
pass
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 4.49153590202 seconds
t1 = timeit.default_timer()
a = 0
for i in range(1, 100000000):
pass
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 7.04547905922 seconds
Приведенный выше пример не отражает ничего лучшего в случае xrange
.
Теперь рассмотрим следующий случай, когда range
действительно очень медленный, по сравнению с xrange
.
import timeit
t1 = timeit.default_timer()
a = 0
for i in xrange(1, 100000000):
if i == 10000:
break
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 0.000764846801758 seconds
t1 = timeit.default_timer()
a = 0
for i in range(1, 100000000):
if i == 10000:
break
t2 = timeit.default_timer()
print "time taken: ", (t2-t1) # 2.78506207466 seconds
С range
он уже создает список от 0 до 100000000 (отнимает много времени), но xrange
является генератором, и он генерирует только числа на основе необходимости, то есть, если итерация продолжается.
В Python-3 реализация функциональности range
такая же, как и для xrange
в Python-2, в то время как в Python-320 >
Счастливое кодирование!!
диапазон(): (1, 10) возвращает список из 1 до 10 чисел и удерживает весь список в памяти.
xrange(): Подобно range(), но вместо того, чтобы возвращать список, возвращается объект, который генерирует числа в диапазоне по запросу. Для циклизации это намного быстрее, чем диапазон() и более эффективный объем памяти. xrange(), как итератор, и генерирует числа по требованию. (Lazy Evaluation)
In [1]: range(1,10)
Out[1]: [1, 2, 3, 4, 5, 6, 7, 8, 9]
In [2]: xrange(10)
Out[2]: xrange(10)
In [3]: print xrange.__doc__
xrange([start,] stop[, step]) -> xrange object
range(x,y)
возвращает список каждого числа между x и y, если вы используете цикл for
, а затем range
работает медленнее. Фактически, range
имеет больший диапазон индексов. range(x.y)
распечатает список всех чисел между x и y
xrange(x,y)
возвращает xrange(x,y)
, но если вы использовали цикл for
, то xrange
работает быстрее. xrange
имеет меньший диапазон индексов. xrange
не только распечатает xrange(x,y)
, но все равно сохранит все числа, которые в нем.
[In] range(1,10)
[Out] [1, 2, 3, 4, 5, 6, 7, 8, 9]
[In] xrange(1,10)
[Out] xrange(1,10)
Если вы используете цикл for
, то он будет работать
[In] for i in range(1,10):
print i
[Out] 1
2
3
4
5
6
7
8
9
[In] for i in xrange(1,10):
print i
[Out] 1
2
3
4
5
6
7
8
9
При использовании петель нет большой разницы, хотя есть разница, когда вы просто печатаете его.
В python 2.x
range (x) возвращает список, который создается в памяти с помощью x элементов.
>>> a = range(5)
>>> a
[0, 1, 2, 3, 4]
xrange (x) возвращает объект xrange, который является генератором obj, который генерирует числа по требованию. они вычисляются во время цикла (Lazy Evaluation).
Для цикла, это немного быстрее, чем диапазон() и более эффективная память.
>>> b = xrange(5)
>>> b
xrange(5)
При тестировании диапазона против xrange в цикле (я знаю, что я должен использовать timeit, но это было быстро взломано из памяти с использованием простого примера понимания списка). Я нашел следующее:
import time
for x in range(1, 10):
t = time.time()
[v*10 for v in range(1, 10000)]
print "range: %.4f" % ((time.time()-t)*100)
t = time.time()
[v*10 for v in xrange(1, 10000)]
print "xrange: %.4f" % ((time.time()-t)*100)
который дает:
$python range_tests.py
range: 0.4273
xrange: 0.3733
range: 0.3881
xrange: 0.3507
range: 0.3712
xrange: 0.3565
range: 0.4031
xrange: 0.3558
range: 0.3714
xrange: 0.3520
range: 0.3834
xrange: 0.3546
range: 0.3717
xrange: 0.3511
range: 0.3745
xrange: 0.3523
range: 0.3858
xrange: 0.3997 <- garbage collection?
Или, используя xrange в цикле for:
range: 0.4172
xrange: 0.3701
range: 0.3840
xrange: 0.3547
range: 0.3830
xrange: 0.3862 <- garbage collection?
range: 0.4019
xrange: 0.3532
range: 0.3738
xrange: 0.3726
range: 0.3762
xrange: 0.3533
range: 0.3710
xrange: 0.3509
range: 0.3738
xrange: 0.3512
range: 0.3703
xrange: 0.3509
Правильно ли тестируется мой фрагмент? Любые комментарии к более медленному экземпляру xrange? Или лучший пример :-)
В некоторых других ответах упоминается, что Python 3 исключил 2.x range
и переименовал 2.x xrange
в range
. Однако, если вы используете 3.0 или 3.1 (чего не должно быть), это фактически несколько другой тип.
Как 3.1 docs говорят:
Объекты Range имеют очень малое поведение: они поддерживают только индексирование, итерацию и функцию
len
.
Однако в 3.2+ range
- полная последовательность - она поддерживает расширенные срезы, а все методы collections.abc.Sequence
с той же семантикой, что и list
. *
И, по крайней мере, в CPython и PyPy (единственные две версии 3.2+, которые существуют в настоящее время), он также имеет реализаторы времени index
и count
и оператор in
(до тех пор, пока вы передаете только целые числа). Это означает, что запись 123456 in r
является разумной в 3.2+, тогда как в 2.7 или 3.1 это было бы ужасной идеей.
* Тот факт, что issubclass(xrange, collections.Sequence)
возвращает True
в 2.6-2.7 и 3.0-3.1, является ошибка, которая была исправлена в 3.2, а не обратно.
xrange() и range() в python работают так же, как и для пользователя, но разница возникает, когда мы говорим о том, как выделяется память при использовании обеих функций.
Когда мы используем range(), мы выделяем память для всех переменных, которые она генерирует, поэтому не рекомендуется использовать с большим no. переменных, которые должны быть сгенерированы.
xrange(), с другой стороны, генерирует только определенное значение за раз и может использоваться только с циклом for для печати всех необходимых значений.
генерирует весь список и возвращает его. xrange нет - он генерирует числа в списке по запросу.
Прочитайте следующее сообщение для сравнения между диапазоном и xrange с графическим анализом.
xrange использует итератор (генерирует значения "на лету" ), диапазон возвращает список.
Что? range
возвращает статический список во время выполнения. xrange
возвращает object
(который действует как генератор, хотя он, конечно, не один), из которого генерируются значения как и когда требуется.
Когда использовать какой?
xrange
, если вы хотите создать список для гигантского диапазона, скажем, 1 миллиард, особенно если у вас есть "чувствительная к памяти система", например, сотовый телефон.range
, если вы хотите перебирать по списку несколько раз.PS: функция Python 3.x range
== Python 2.x xrange
.
При необходимости сканирования/печати 0-N элементов диапазон и xrange работают следующим образом.
range() - создает новый список в памяти и принимает от 0 до N элементов (полностью N + 1) и печатает их. xrange() - создает экземпляр итератора, который сканирует элементы и сохраняет только текущий найденный элемент в памяти, поэтому все время использует одинаковый объем памяти.
В случае, если требуемый элемент находится несколько в начале списка, тогда он сохраняет хорошее количество времени и памяти.
Разница уменьшается при меньших аргументах до range(..)
/xrange(..)
:
$ python -m timeit "for i in xrange(10111):" " for k in range(100):" " pass"
10 loops, best of 3: 59.4 msec per loop
$ python -m timeit "for i in xrange(10111):" " for k in xrange(100):" " pass"
10 loops, best of 3: 46.9 msec per loop
В этом случае xrange(100)
эффективнее всего на 20%.
Все это очень объяснили. Но я хотел, чтобы он видел это для себя. Я использую python3. Итак, я открыл монитор ресурсов (в Windows!) И сначала выполнил следующую команду:
a=0
for i in range(1,100000):
a=a+i
а затем проверили изменение в памяти "Использовать". Это было незначительно. Затем я выполнил следующий код:
for i in list(range(1,100000)):
a=a+i
И мгновенно потребовалось большое количество памяти для использования. И я был убежден. Вы можете попробовать это для себя.
Если вы используете Python 2X, замените "range()" на "xrange()" в первом коде и "list (range())" на "range()".
Диапазон возвращает список, а xrange возвращает объект xrange, который принимает одну и ту же память независимо от диапазона size, так как в этом случае создается только один элемент и доступен для каждой итерации, тогда как в случае использования диапазона все элементы генерируются сразу и доступны в памяти.
range: -range будет заполнять все сразу. Это означает, что каждое число диапазона будет занимать память.
xrange: -xrange - это что-то вроде генератора, он появится в изображении, если вам нужен диапазон чисел, но вы не хотите, чтобы они были сохранены, например, когда вы хотите использовать для эффективной работы с памятью loop.so.
В справочных документах.
Python 2.7.12
>>> print range.__doc__
range(stop) -> list of integers
range(start, stop[, step]) -> list of integers
Return a list containing an arithmetic progression of integers.
range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
When step is given, it specifies the increment (or decrement).
For example, range(4) returns [0, 1, 2, 3]. The end point is omitted!
These are exactly the valid indices for a list of 4 elements.
>>> print xrange.__doc__
xrange(stop) -> xrange object
xrange(start, stop[, step]) -> xrange object
Like range(), but instead of returning a list, returns an object that
generates the numbers in the range on demand. For looping, this is
slightly faster than range() and more memory efficient.
Python 3.5.2
>>> print(range.__doc__)
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).
>>> print(xrange.__doc__)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'xrange' is not defined
Отличие очевидно. В Python 2.x, range
возвращает список, xrange
возвращает объект xrange, который является итерируемым.
В Python 3.x, range
становится xrange
Python 2.x и xrange
удаляется.
Кроме того, если list(xrange(...))
do list(xrange(...))
будет эквивалентен range(...)
.
Поэтому list
медленный.
Также xrange
действительно не полностью завершает последовательность
Итак, почему это не список, это объект xrange
Смотрите post, чтобы найти разницу между диапазоном и xrange:
Цитата:
range
возвращает именно то, что вы думаете: список последовательных целые числа определенной длины, начинающиеся с 0.xrange
, однако, возвращает "объект xrange", который очень похож на итератор