В чем разница между функциями range и xrange в Python 2.X?

По-видимому, xrange быстрее, но я понятия не имею, почему это быстрее (и нет доказательств, кроме анекдотических до сих пор, что это быстрее) или что помимо этого отличается

for i in range(0, 20):
for i in xrange(0, 20):
623
18 сент. '08 в 20:52
источник поделиться
29 ответов

диапазон создает список, поэтому, если вы делаете range(1, 10000000) он создает список в памяти с 9999999 элементами.

xrange - объект последовательности, который оценивается лениво.

Он должен быть добавлен из подсказки @Thiago, что в python3 диапазон делает эквивалент python xrange

712
18 сент. '08 в 20:55
источник

Связанные вопросы


Похожие вопросы

диапазон создает список, поэтому, если вы делаете range(1, 10000000) он создает список в памяти с 9999999 элементами.

xrange - это генератор, поэтому он представляет собой объект последовательности , который оценивается лениво.

Это верно, но в Python 3, .range() будет реализован Python 2. .xrange(). Если вам нужно создать список, вам нужно будет:

list(range(1,100))
213
18 сент. '08 в 21:08
источник

Помните, используйте модуль 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() даст вам хорошее поведение итератора в любом случае.

100
19 сент. '08 в 1:11
источник

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, но без ограничений на минимальные и максимальные конечные точки.

64
18 сент. '08 в 21:13
источник

xrange возвращает итератор и сохраняет только один номер в памяти за раз. диапазон сохраняет весь список номеров в памяти.

37
18 сент. '08 в 20:55
источник

Проведите некоторое время с Справочник по библиотеке. Чем более вы знакомы с ним, тем быстрее вы сможете найти ответы на такие вопросы. Особенно важны первые несколько глав о встроенных объектах и ​​типах.

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

Другим способом поиска быстрой информации о конструкции Python является docstring и help-function:

print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)
28
18 сент. '08 в 20:55
источник

range() vs xrange() в python:

range() и xrange() - это две функции, которые могут использоваться для повторения определенного количества раз для циклов в Python. В Python 3 отсутствует xrange, но функция диапазона ведет себя как xrange в Python 2. Если вы хотите написать код, который будет работать как на Python 2, так и на Python 3, вы должны использовать range().

range() - возвращает список номеров, созданных с использованием функции range().

xrange() - эта функция возвращает объект-генератор, который может использоваться для отображения чисел только путем циклирования. Только конкретный диапазон отображается по запросу и, следовательно, называется "ленивая оценка".

Оба они реализованы по-разному и имеют разные характеристики, связанные с ними. Точками сравнения являются:

  1. Тип возвращаемого значения Тип использования памяти
  2. объем памяти
  3. Использование
  4. скорость

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. Если вы хотите написать код, который будет работать как на Python 2, так и на Python 3, используйте range(), поскольку функция xrange устарела в Python 3.
  2. range() быстрее, если итерация по одной и той же последовательности несколько раз.
  3. xrange() должен каждый раз восстанавливать целочисленный объект, но range() будет иметь действительные целочисленные объекты. (Однако он всегда будет хуже работать с точки зрения памяти).

Ссылка

17
05 нояб. '17 в 10:02
источник

Я шокирован, никто не читает doc:

Эта функция очень похожа на range(), но возвращает объект xrange вместо списка. Это непрозрачный тип последовательности, который дает те же значения, что и соответствующий список, без фактического их одновременного хранения. Преимущество xrange() over range() минимально (поскольку xrange() по-прежнему нужно создавать значения, когда их спрашивают), за исключением случаев, когда очень сильно используется диапазон на машине с голодающей памятью или когда все элементы диапазона никогда не используется (например, когда цикл обычно заканчивается с помощью break).

12
07 апр. '14 в 9:25
источник
Диапазон

создает список, поэтому, если вы делаете диапазон (1, 10000000), он создает список в памяти с 10000000 элементами. xrange - это генератор, поэтому он лениво оценивает.

Это дает вам два преимущества:

  • Вы можете переименовывать более длинные списки, не получая MemoryError.
  • Поскольку он решает каждый номер лениво, если вы остановите итерацию раньше, вы не будете тратить время на создание всего списка.
12
18 сент. '08 в 21:44
источник

В этом простом примере вы найдете преимущество 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 >

Счастливое кодирование!!

10
22 окт. '16 в 14:34
источник

Это по соображениям оптимизации.

range() создаст список значений от начала до конца (0.. 20 в вашем примере). Это станет дорогостоящей операцией на очень больших диапазонах.

xrange(), с другой стороны, намного оптимизирован. он будет вычислять только следующее значение при необходимости (через объект последовательности xrange) и не создает список всех значений, таких как range().

10
18 сент. '08 в 20:59
источник

диапазон(): (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
8
23 июня '15 в 11:16
источник

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

При использовании петель нет большой разницы, хотя есть разница, когда вы просто печатаете его.

7
12 июля '16 в 3:05
источник

В 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)
6
28 февр. '16 в 12:42
источник

При тестировании диапазона против 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? Или лучший пример :-)

5
18 марта '11 в 15:04
источник

В некоторых других ответах упоминается, что 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, а не обратно.

5
07 мая '15 в 0:57
источник

xrange() и range() в python работают так же, как и для пользователя, но разница возникает, когда мы говорим о том, как выделяется память при использовании обеих функций.

Когда мы используем range(), мы выделяем память для всех переменных, которые она генерирует, поэтому не рекомендуется использовать с большим no. переменных, которые должны быть сгенерированы.

xrange(), с другой стороны, генерирует только определенное значение за раз и может использоваться только с циклом for для печати всех необходимых значений.

4
19 янв. '16 в 15:48
источник

Прочитайте следующее сообщение для сравнения между диапазоном и xrange с графическим анализом.

Диапазон Python Vs xrange

3
01 авг. '15 в 14:37
источник
Диапазон

генерирует весь список и возвращает его. xrange нет - он генерирует числа в списке по запросу.

3
18 сент. '08 в 20:55
источник

Что?
range возвращает статический список во время выполнения.
xrange возвращает object (который действует как генератор, хотя он, конечно, не один), из которого генерируются значения как и когда требуется.

Когда использовать какой?

  • Используйте xrange, если вы хотите создать список для гигантского диапазона, скажем, 1 миллиард, особенно если у вас есть "чувствительная к памяти система", например, сотовый телефон.
  • Используйте range, если вы хотите перебирать по списку несколько раз.

PS: функция Python 3.x range == Python 2.x xrange.

2
26 нояб. '14 в 11:18
источник

xrange использует итератор (генерирует значения "на лету" ), диапазон возвращает список.

2
18 сент. '08 в 20:55
источник

Все это очень объяснили. Но я хотел, чтобы он видел это для себя. Я использую 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()".

1
24 июля '17 в 13:37
источник

Разница уменьшается при меньших аргументах до 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%.

1
30 мая '15 в 14:23
источник

При необходимости сканирования/печати 0-N элементов диапазон и xrange работают следующим образом.

range() - создает новый список в памяти и принимает от 0 до N элементов (полностью N + 1) и печатает их. xrange() - создает экземпляр итератора, который сканирует элементы и сохраняет только текущий найденный элемент в памяти, поэтому все время использует одинаковый объем памяти.

В случае, если требуемый элемент находится несколько в начале списка, тогда он сохраняет хорошее количество времени и памяти.

1
15 янв. '14 в 15:45
источник

Кроме того, если list(xrange(...)) do list(xrange(...)) будет эквивалентен range(...).

Поэтому list медленный.

Также xrange действительно не полностью завершает последовательность

Итак, почему это не список, это объект xrange

0
08 окт. '18 в 8:46
источник

Диапазон возвращает список, а xrange возвращает объект xrange, который принимает одну и ту же память независимо от диапазона size, так как в этом случае создается только один элемент и доступен для каждой итерации, тогда как в случае использования диапазона все элементы генерируются сразу и доступны в памяти.

0
03 янв. '15 в 9:31
источник

range: -range будет заполнять все сразу. Это означает, что каждое число диапазона будет занимать память.

xrange: -xrange - это что-то вроде генератора, он появится в изображении, если вам нужен диапазон чисел, но вы не хотите, чтобы они были сохранены, например, когда вы хотите использовать для эффективной работы с памятью loop.so.

0
10 янв. '17 в 9:00
источник

В справочных документах.

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 удаляется.

0
19 авг. '17 в 8:28
источник

Смотрите post, чтобы найти разницу между диапазоном и xrange:

Цитата:

range возвращает именно то, что вы думаете: список последовательных целые числа определенной длины, начинающиеся с 0. xrange, однако, возвращает "объект xrange", который очень похож на итератор

-1
18 сент. '08 в 20:54
источник

Посмотрите другие вопросы по меткам или Задайте вопрос