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

python loops range python-2.x xrange

353171 просмотра

28 ответа

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

for i in range(0, 20):
for i in xrange(0, 20):
Автор: Teifion Источник Размещён: 16.08.2019 09:10

Ответы (28)


766 плюса

Решение

В Python 2.x:

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

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

В Python 3 rangeделает эквивалент Python xrange, и чтобы получить список, вы должны использовать list(range(...)).

Автор: Charles Размещён: 18.09.2008 05:55

217 плюса

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

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

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

list(range(1,100))
Автор: Corey Размещён: 18.09.2008 06:08

109 плюса

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

Автор: John Fouhy Размещён: 18.09.2008 10:11

64 плюса

xrangeхранит только параметры диапазона и генерирует числа по запросу. Однако реализация Python на C в настоящее время ограничивает свои аргументы 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но без ограничений на минимальные и максимальные конечные точки.

Автор: efotinis Размещён: 18.09.2008 06:13

38 плюса

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

Автор: Ben Hoffstein Размещён: 18.09.2008 05:55

28 плюса

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

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

Другой способ найти быструю информацию о конструкции Python - это строка документации и функция помощи:

print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)
Автор: Antti Rasinen Размещён: 18.09.2008 05:55

13 плюса

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

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

  1. Вы можете перебирать более длинные списки, не получая MemoryError.
  2. Поскольку каждое число лениво разрешается, если вы остановите итерацию раньше, вы не будете тратить время на создание всего списка.
Автор: Lucas S. Размещён: 18.09.2008 06:44

13 плюса

Я в шоке, никто не читал док :

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

Автор: Kishor Pawar Размещён: 07.04.2014 06:25

11 плюса

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

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

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

Автор: QAZ Размещён: 18.09.2008 05:59

11 плюса

Вы найдете преимущество xrangeнад 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, в то время как xrangeв Python-3 они покончили с этим.

Удачного кодирования!

Автор: User_Targaryen Размещён: 22.10.2016 11:34

8 плюса

range (): range (1, 10) возвращает список от 1 до 10 чисел и сохраняет весь список в памяти.

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

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
Автор: Tushar.PUCSD Размещён: 23.06.2015 08:16

8 плюса

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

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

Автор: Supercolbat Размещён: 12.07.2016 12:05

6 плюса

В Python 2.x

range (x) возвращает список, созданный в памяти с x элементами.

>>> a = range(5)
>>> a
[0, 1, 2, 3, 4]

xrange (x) возвращает объект xrange, который является генератором obj, который генерирует числа по требованию. они вычисляются во время цикла for (Lazy Evaluation).

Для цикла это немного быстрее, чем range () и более эффективно использовать память.

>>> b = xrange(5)
>>> b
xrange(5)
Автор: Siyaram Malav Размещён: 28.02.2016 09:42

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? Или лучший пример :-)

Автор: Dave Everitt Размещён: 18.03.2011 12:04

5 плюса

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

Как сказано в документах 3.1 :

Объекты Range имеют очень небольшое поведение: они поддерживают только индексацию, итерацию и lenфункцию.

Тем не менее, в 3.2+, rangeэто полная последовательность - она ​​поддерживает расширенные слайсы и все методы collections.abc.Sequenceс той же семантикой, что и a 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 и не портирована.

Автор: abarnert Размещён: 06.05.2015 09:57

4 плюса

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

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

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

Автор: Lakshaya Maheshwari Размещён: 19.01.2016 12:48

3 плюса

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

Автор: Eddie Deyo Размещён: 18.09.2008 05:55

3 плюса

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

Диапазон Python против Xrange

Автор: Harsha Vardhan Размещён: 01.08.2015 11:37

2 плюса

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

Автор: hacama Размещён: 18.09.2008 05:55

2 плюса

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

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

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

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

Автор: kmario23 Размещён: 26.11.2014 08:18

1 плюс

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

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

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

Автор: SomeDoubts Размещён: 15.01.2014 12:45

1 плюс

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

Автор: Evgeni Sergeev Размещён: 30.05.2015 11:23

1 плюс

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

Автор: ANKUR SATYA Размещён: 24.07.2017 10:37

0 плюса

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

Автор: user299567 Размещён: 03.01.2015 06:31

0 плюса

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

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

Автор: tejaswini teju Размещён: 10.01.2017 06:00

0 плюса

С помощью документов.

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становится xrangePython 2.x и xrangeудаляется.

Автор: Rajendra Uppal Размещён: 19.08.2017 05:28

0 плюса

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

Так listмедленно.

Также на xrangeсамом деле не полностью закончить последовательность

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

Автор: U10-Forward Размещён: 08.10.2018 05:46

-1 плюса

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

Цитировать:

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

Автор: Oko Размещён: 18.09.2008 05:54
32x32