Pregunta

Aparentemente, xrange es más rápido, pero no tengo idea de por qué es más rápido (y no hay pruebas además de lo anecdótico hasta ahora de que es más rápido) o qué tiene de diferente además de eso.

for i in range(0, 20):
for i in xrange(0, 20):
¿Fue útil?

Solución

range crea una lista, así que si lo haces range(1, 10000000) crea una lista en la memoria con 9999999 elementos.

xrange es un objeto de secuencia que se evalúa de forma perezosa.

Se debe agregar, a partir de la sugerencia de @Thiago, que en python3, range es el equivalente al xrange de python.

Otros consejos

range crea una lista, así que si lo haces range(1, 10000000) crea una lista en la memoria con 9999999 elementos.

xrange es un generador, por lo que es un objeto de secuencia es un que evalúa con pereza.

Esto es cierto, pero en Python 3, .range() será implementado por Python 2 .xrange().Si realmente necesita generar la lista, deberá hacer:

list(range(1,100))

Recuerde, utilice el timeit Módulo para probar cuál de los pequeños fragmentos de código es más rápido.

$ 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

Personalmente siempre uso .range(), a menos que estuviera tratando con en realidad listas enormes: como puede ver, en términos de tiempo, para una lista de un millón de entradas, la sobrecarga adicional es de solo 0,04 segundos.Y como señala Corey, en Python 3.0 .xrange() se irá y .range() le dará un buen comportamiento de iterador de todos modos.

xrange solo almacena los parámetros de rango y genera los números a pedido.Sin embargo, la implementación C de Python actualmente restringe sus argumentos a 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]

Tenga en cuenta que en Python 3.0 solo hay range y se comporta como el 2.x xrange pero sin las limitaciones en los puntos finales mínimo y máximo.

xrange devuelve un iterador y solo mantiene un número en la memoria a la vez.range mantiene la lista completa de números en la memoria.

Pasa algún tiempo con el Referencia de la biblioteca.Cuanto más familiarizado esté con él, más rápido podrá encontrar respuestas a preguntas como esta.Especialmente importantes son los primeros capítulos sobre tipos y objetos integrados.

La ventaja del tipo XRange es que un objeto XRange siempre tomará la misma cantidad de memoria, sin importar el tamaño del rango que representa.No hay ventajas de rendimiento consistentes.

Otra forma de encontrar información rápida sobre una construcción de Python es la cadena de documentación y la función de ayuda:

print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)

range crea una lista, por lo que si lo hace range(1, 10000000) crea una lista en la memoria con 10000000 elementos.xrange es un generador, por lo que se evalúa de forma perezosa.

Esto te trae dos ventajas:

  1. Puede iterar listas más largas sin obtener un MemoryError.
  2. Como resuelve cada número de forma perezosa, si detiene la iteración antes de tiempo, no perderá tiempo creando la lista completa.

Me sorprende que nadie haya leído doc:

Esta función es muy similar a range(), pero devuelve un xrange objeto en lugar de una lista.Este es un tipo de secuencia opaca que produce los mismos valores que la lista correspondiente, sin almacenarlos todos simultáneamente.La ventaja de xrange() encima range() es mínimo (ya que xrange() todavía tiene que crear los valores cuando se los solicita) excepto cuando se usa un rango muy grande en una máquina con falta de memoria o cuando todos los elementos del rango nunca se usan (como cuando el bucle generalmente termina con break).

Es por motivos de optimización.

range() creará una lista de valores de principio a fin (0 ..20 en tu ejemplo).Esto resultará una operación costosa en distancias muy grandes.

xrange() por otro lado está mucho más optimizado.solo calculará el siguiente valor cuando sea necesario (a través de un objeto de secuencia xrange) y no crea una lista de todos los valores como lo hace range().

Encontrarás la ventaja de xrange encima range en este sencillo ejemplo:

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

El ejemplo anterior no refleja nada sustancialmente mejor en caso de xrange.

Ahora observe el siguiente caso donde range es realmente muy lento, en comparación con 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

Con range, ya crea una lista de 0 a 100000000 (consume mucho tiempo), pero xrange es un generador y solo genera números según la necesidad, es decir, si la iteración continúa.

En Python-3, la implementación del range la funcionalidad es la misma que la de xrange en Python-2, mientras que han eliminado xrange en Python-3

¡Feliz codificación!

rango(): range(1, 10) devuelve una lista de 1 a 10 números y mantiene la lista completa en la memoria.

rango x(): Como range(), pero en lugar de devolver una lista, devuelve un objeto que genera los números en el rango a pedido.Para bucles, esto es ligeramente más rápido que range() y más eficiente en memoria.Objeto xrange() como un iterador y genera los números a pedido. (Evaluación diferida)

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) devuelve una lista de cada número entre x e y si usa un for bucle, entonces range es más lento.De hecho, range tiene un rango de índice mayor. range(x.y) imprimirá una lista de todos los números entre x e y

xrange(x,y) devoluciones xrange(x,y) pero si usaras un for bucle, entonces xrange es más rápido. xrange tiene un rango de índice más pequeño. xrange no sólo se imprimirá xrange(x,y) pero aún conservará todos los números que contiene.

[In] range(1,10)
[Out] [1, 2, 3, 4, 5, 6, 7, 8, 9]
[In] xrange(1,10)
[Out] xrange(1,10)

Si usas un for bucle, entonces funcionaría

[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

No hay mucha diferencia cuando se usan bucles, ¡aunque sí hay una diferencia cuando simplemente se imprime!

En Python 2.x

rango(x) devuelve una lista, que se crea en la memoria con x elementos.

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

rango x(x) devuelve un objeto xrange que es un obj generador que genera los números a pedido.se calculan durante el bucle for (evaluación diferida).

Para bucles, esto es ligeramente más rápido que range() y más eficiente en memoria.

>>> b = xrange(5)
>>> b
xrange(5)

Al probar el rango contra xrange en un bucle (sé que debería usar cronométralo, pero esto fue rápidamente eliminado de la memoria usando un ejemplo simple de comprensión de listas) Encontré lo siguiente:

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)

lo que da:

$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?

O, usando xrange en el bucle 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

¿Mi fragmento se está probando correctamente?¿Algún comentario sobre la instancia más lenta de xrange?O un mejor ejemplo :-)

Algunas de las otras respuestas mencionan que Python 3 eliminó 2.x. range y renombrado 2.x xrange a range.Sin embargo, a menos que estés usando 3.0 o 3.1 (que nadie debería usar), en realidad es un tipo algo diferente.

Como los documentos 3.1 decir:

Los objetos de rango tienen muy poco comportamiento:sólo admiten la indexación, la iteración y la len función.

Sin embargo, en 3.2+, range es una secuencia completa: admite cortes extendidos y todos los métodos de collections.abc.Sequence con la misma semántica que un list.*

Y, al menos en CPython y PyPy (las únicas dos implementaciones 3.2+ que existen actualmente), también tiene implementaciones en tiempo constante del index y count métodos y el in operador (siempre que solo le pase números enteros).Esto significa escribir 123456 in r es razonable en 3.2+, mientras que en 2.7 o 3.1 sería una idea horrible.


* El hecho de que issubclass(xrange, collections.Sequence) devoluciones True en 2.6-2.7 y 3.0-3.1 es un insecto eso se solucionó en 3.2 y no se respaldó.

xrange() y range() en Python funcionan de manera similar al usuario, pero la diferencia surge cuando hablamos de cómo se asigna la memoria al usar ambas funciones.

Cuando usamos range() asignamos memoria para todas las variables que está generando, por lo que no se recomienda usar con números mayores.de variables a generar.

xrange(), por otro lado, genera solo un valor particular a la vez y solo se puede usar con el bucle for para imprimir todos los valores requeridos.

range genera la lista completa y la devuelve.xrange no lo hace: genera los números en la lista a pedido.

Lea la siguiente publicación para conocer la comparación entre range y xrange con análisis gráfico.

Rango de Python Vs xrange

xrange usa un iterador (genera valores sobre la marcha), range devuelve una lista.

¿Qué?
range devuelve una lista estática en tiempo de ejecución.
xrange devuelve un object (que actúa como un generador, aunque ciertamente no lo es) a partir del cual se generan valores cuando sea necesario.

¿Cuándo usar cuál?

  • Usar xrange si desea generar una lista para un rango gigantesco, digamos mil millones, especialmente cuando tiene un "sistema sensible a la memoria" como un teléfono celular.
  • Usar range si desea repetir la lista varias veces.

PD:Python 3.x range función == Python 2.x xrange función.

Si se requiere escanear/imprimir elementos 0-N, range y xrange funcionan de la siguiente manera.

range(): crea una nueva lista en la memoria y toma los elementos completos de 0 a N (totalmente N+1) y los imprime.xrange(): crea una instancia de iterador que escanea los elementos y mantiene solo el elemento encontrado actualmente en la memoria, por lo que utiliza la misma cantidad de memoria todo el tiempo.

En caso de que el elemento requerido esté al principio de la lista, se ahorra una buena cantidad de tiempo y memoria.

La diferencia disminuye para argumentos más pequeños. 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

En este caso xrange(100) es sólo alrededor de un 20% más eficiente.

Todo el mundo lo ha explicado estupendamente.Pero quería verlo por mí mismo.Yo uso python3.Entonces, abrí el monitor de recursos (¡en Windows!) y primero ejecuté el siguiente comando:

a=0
for i in range(1,100000):
    a=a+i

y luego verificó el cambio en la memoria 'En uso'.Fue insignificante.Luego, ejecuté el siguiente código:

for i in list(range(1,100000)):
    a=a+i

Y se necesitó una gran parte de la memoria para su uso, al instante.Y estaba convencido.Puedes probarlo por ti mismo.

Si está utilizando Python 2X, reemplace 'range()' con 'xrange()' en el primer código y 'list(range())' con 'range()'.

Rango devuelve un lista mientras rango x devuelve un rango x objeto que toma la misma memoria independientemente del tamaño del rango, como en este caso, solo se genera y está disponible un elemento por iteración, mientras que en el caso de usar el rango, todos los elementos se generan a la vez y están disponibles en la memoria.

rango: -el rango llenará todo a la vez, lo que significa que cada número del rango ocupará la memoria.

xrange: -xrange es algo así como un generador, aparecerá en la imagen cuando desee el rango de números pero no desee que se almacenen, como cuando desee usarlos en el bucle for. Por lo tanto, la memoria es eficiente.

De los documentos de ayuda.

Pitón 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.

Pitón 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

La diferencia es evidente.En Python 2.x, range devuelve una lista, xrange devuelve un objeto xrange que es iterable.

En Python 3.x, range se convierte xrange de Python 2.x, y xrange es removido.

Además, si lo hace list(xrange(...)) será equivalente a range(...).

Entonces list es lento.

También xrange realmente no termina completamente la secuencia

Por eso no es una lista, es una xrange objeto

Mira esto correo para encontrar la diferencia entre rango y xrange:

Citar:

range devuelve exactamente lo que piensas:Una lista de enteros consecutivos, de una longitud definida que comienza con 0. xrange, sin embargo, devuelve un "objeto xrange", que actúa en gran medida como un iterador

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top