¿Cuál es la diferencia entre las funciones de rango y rango en Python 2.X?

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

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

el rango crea una lista, por lo que si realiza el range(1, 10000000) , crea una lista en la memoria con 9999999 elementos.

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

Se debe agregar de la sugerencia de @ Thiago, que en python3, el rango hace el equivalente a la gama de Python.

el rango crea una lista, por lo que si realiza el range(1, 10000000) , crea una lista en la memoria con 9999999 elementos.

xrange es un generador, por lo que es una secuencia de objetos que se evalúa perezosamente.

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

 list(range(1,100)) 

¡Recuerde, use el módulo timeit 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 esté manejando listas realmente enormes, como se puede ver, en el 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() desaparecerá y .range() te 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 en C de Python actualmente restringe sus argumentos a largos en C:

 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 xrange 2.x pero sin las limitaciones de los puntos finales mínimos y máximos.

xrange devuelve un iterador y solo mantiene un número en la memoria a la vez. El rango mantiene toda la lista de números en la memoria.

Pasa algún tiempo con la Biblioteca de Referencia . 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 objetos y tipos incorporados.

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 represente. No hay ventajas de rendimiento consistentes.

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

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

Estoy sorprendido de que nadie lea el documento :

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

el rango crea una lista, por lo que si lo hace el rango (1, 10000000) crea una lista en la memoria con 10000000 elementos. xrange es un generador, por lo que evalúa perezosamente.

Esto te trae dos ventajas:

  1. Puede iterar listas más largas sin obtener un MemoryError .
  2. A medida que se resuelve cada número perezosamente, si detiene la iteración anticipadamente, no perderá tiempo creando toda la lista.

Es por razones de optimización.

range () creará una lista de valores de principio a fin (0 .. 20 en su ejemplo). Esto se convertirá en una operación costosa en rangos 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 el rango ().

Encontrará la ventaja de xrange sobre el 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 en el que el range es realmente lento, comparado 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 el range , ya crea una lista de 0 a 100000000 (requiere 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 de la funcionalidad de range es la misma que la de xrange en Python-2, mientras que eliminaron la xrange en Python-3.

Feliz codificacion !!

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

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

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

xrange(x,y) devuelve xrange(x,y) pero si usó un bucle for , entonces xrange es más rápido. xrange tiene un rango de índice más pequeño. xrange no solo imprimirá xrange(x,y) sino que mantendrá todos los números que hay en ella.

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

Si usa un bucle for , 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 hay una diferencia cuando solo se imprime!

En python 2.x

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

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

xrange (x) devuelve un objeto xrange que es un obj generador que genera los números a pedido. se calculan durante for-loop (Evaluación perezosa).

Para bucles, esto es un poco más rápido que el rango () y más eficiente en memoria.

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

Cuando probé el rango contra xrange en un bucle (sé que debería usar timeit , pero esto fue hackeado rápidamente de la memoria usando un ejemplo de comprensión de lista simple) 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 prueba de fragmentos está 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ó el range de 2.x y renombró el range 2.x a range . Sin embargo, a menos que esté utilizando 3.0 o 3.1 (que nadie debería), en realidad es un tipo algo diferente.

Como dicen los documentos 3.1 :

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

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

Y, al menos en CPython y PyPy (las únicas dos implementaciones 3.2+ que existen actualmente), también tiene implementaciones de tiempo constante de los métodos de index y count y del operador in (siempre y cuando solo pases los enteros). Esto significa que 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) devuelva True en 2.6-2.7 y 3.0-3.1 es un error que se corrigió en 3.2 y no se realizó una copia de seguridad.

xrange () y range () en python funcionan de manera similar a la del usuario, pero la diferencia se produce cuando estamos hablando de cómo se asigna la memoria al usar ambas funciones.

Cuando estamos usando range (), asignamos memoria para todas las variables que está generando, por lo que no se recomienda usar con un no mayor. de variables a generar.

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

El rango 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 la comparación entre rango y rango con análisis gráfico.

Rango de Python Vs xrange

xrange utiliza un iterador (genera valores sobre la marcha), el rango 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 se requieren.

¿Cuándo usar cuál?

  • Use xrange si desea generar una lista para un rango gigantesco, digamos 1 billón, especialmente cuando tiene un “sistema sensible a la memoria” como un teléfono celular.
  • Utilice el range si desea iterar sobre la lista varias veces.

PS: Función de range Python 3.x == Función xrange Python 2.x.

En un requisito para escanear / imprimir elementos de 0-N, el rango y el rango de trabajo 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 a través de los elementos y mantiene solo el elemento encontrado actual en la memoria, por lo tanto, utiliza la misma cantidad de memoria todo el tiempo.

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

La diferencia disminuye para los argumentos más pequeños al 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 solo un 20% más eficiente.

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

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

y luego verificó el cambio en la memoria ‘En uso’. Fue insignificante. Entonces, corrí el siguiente código:

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

Y tomó 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 ()’.

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

rango: el rango llenará todo de una 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 desea que se almacenen, como cuando desea usar la memoria de loop.so.

De los documentos de ayuda.

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 "", line 1, in  NameError: name 'xrange' is not defined 

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

En Python 3.x, el range convierte en xrange de Python 2.x, y xrange se elimina.

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

Así que la list es lenta.

También xrange realmente no termina completamente la secuencia

Por eso no es una lista, es un objeto de xrange

Vea esta publicación para encontrar la diferencia entre rango y rango:

Citar:

range devuelve exactamente lo que piensa: una lista de enteros consecutivos, de una longitud definida que comienza con 0. xrange , sin embargo, devuelve un “objeto de rango” , que actúa como un iterador