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

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

for i in range(0, 20):
for i in xrange(0, 20):

28 ответов


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

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

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


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

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

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

list(range(1,100))

помните, использовать модуль раз все проверить, какие из малых snipps кода быстрее!

$ 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 исчезнет, и диапазон все равно даст вам хорошее поведение итератора.


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


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

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

  • операции Использование
  • скорость
  • 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. Память:

    переменная, хранящая диапазон, созданный range () занимает больше памяти по сравнению с переменной, хранящей диапазон с помощью 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, операции, связанные с list, не могут быть применены к ним, следовательно, недостаток.

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

    ссылка


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

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

    1. вы можете повторять более длинные списки, не получая MemoryError.
    2. как он решает каждое число лениво, если вы остановите итерацию рано, вы не будете тратить время на создание всего списка.

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

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


    Это по причинам оптимизации.

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

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


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

    Удачи В Кодировании!!



    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

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

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

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

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

    >>> 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.х range и переименован в 2.х xrange to range. Однако, если вы не используете 3.0 или 3.1 (чего не должно быть), это на самом деле несколько другой тип.

    As 3.1 docs говорят:

    объекты диапазона имеют очень мало поведения: они поддерживают только индексирование, итерацию и .

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


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


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

    диапазон Python против xrange


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


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

    когда какую использовать?

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

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


    по требованию для сканирования / печати 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% более эффективное.


    все объяснили это очень. Но я хотел, чтобы он увидел это сам. Я использую питон3. Итак, я открыл Монитор ресурсов (в 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 объект, который занимает одну и ту же память независимо от размера диапазона,так как в этом случае генерируется и доступен только один элемент на итерацию,тогда как в случае использования диапазона все элементы генерируются сразу и доступны в памяти.


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

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


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

    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 удалены.


    посмотреть этот в должности чтобы найти разницу между диапазоном и xrange:

    цитата:

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