Respuestas:
En Python 2.x:
range
crea una lista, así que si lo hace range(1, 10000000)
, crea una lista en la memoria con 9999999
elementos.
xrange
es un objeto de secuencia que se evalúa perezosamente.
En Python 3, range
hace el equivalente de Python xrange
, y para obtener la lista, debe usar list(range(...))
.
xrange(x).__iter__()
Es un generador.
i
se evalúa a demanda en lugar de en la inicialización.
range crea una lista, por lo que si lo hace
range(1, 10000000)
, crea una lista en la memoria con9999999
elementos.
xrange
es un generador, por lo quees un objeto de secuenciaes unaque evalúa pereza.
Esto es cierto, pero en Python 3, Python 2 .range()
lo implementará .xrange()
. Si realmente necesita generar la lista, deberá hacer lo siguiente:
list(range(1,100))
¡Recuerde, use 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 lidiando con listas realmente enormes, como puede ver, en cuanto al 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()
le dará un buen comportamiento de iterador de todos modos.
python -m timeit "for i in xrange(1000000):" " pass"
the extra overhead is only 0.04 seconds
no es la forma correcta de verla, (90.5-51.1)/51.1 = 1.771 times slower
es correcta porque transmite que si este es el bucle central de su programa, puede potencialmente obstaculizarlo. Sin embargo, si esta es una parte pequeña, 1.77x no es mucho.
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 C largos:
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 existe range
y se comporta como el 2.x xrange
pero sin las limitaciones en los puntos finales mínimos y máximos.
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.
xrange
no no devolver un iterador.
and only keeps one number in memory at a time
y donde se colocan el resto por favor guíame ..
Pase algún tiempo con la 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 objetos y tipos incorporados.
La ventaja del tipo xrange es que un objeto xrange siempre tendrá la misma cantidad de memoria, sin importar el tamaño del rango que representa. No hay ventajas consistentes de rendimiento.
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)
Estoy sorprendido de que nadie lea el documento :
Esta función es muy similar a
range()
, pero devuelve unxrange
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 dexrange()
overrange()
es mínima (ya quexrange()
todavía tiene que crear los valores cuando se los solicite), excepto cuando se usa un rango muy grande en una máquina sin memoria o cuando nunca se usan todos los elementos del rango (como cuando el ciclo está generalmente terminado conbreak
).
range crea una lista, por lo que si hace range (1, 10000000) crea una lista en memoria con 10000000 elementos. xrange es un generador, por lo que evalúa perezosamente.
Esto te trae dos ventajas:
MemoryError
.Encontrará la ventaja de xrange
más range
en este simple 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 mira 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 en función de la necesidad, es decir, si la iteración continúa.
En Python-3, la implementación de la range
funcionalidad es la misma que xrange
en Python-2, mientras que se ha eliminado xrange
en Python-3
Feliz codificación !!
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 creará una lista de todos los valores como hace range ().
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 más grande. range(x.y)
imprimirá una lista de todos los números entre x e y
xrange(x,y)
vuelve xrange(x,y)
pero si usaste un for
bucle, entonces xrange
es más rápido. xrange
tiene un rango de índice más pequeño. xrange
no solo se imprimirá, xrange(x,y)
sino que tambié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 usa 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 al usar bucles, aunque hay una diferencia cuando solo se imprime!
range (): range (1, 10) devuelve una lista de 1 a 10 números y mantiene la lista completa en la memoria.
xrange (): al igual que range (), pero en lugar de devolver una lista, devuelve un objeto que genera los números en el rango a pedido. Para el bucle, esto es ligeramente más rápido que range () y más eficiente en memoria. xrange () objeto 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
Algunas de las otras respuestas mencionan que Python 3 eliminó 2.x's range
y renombró 2.x's xrange
a range
. Sin embargo, a menos que esté utilizando 3.0 o 3.1 (que nadie debería usar), en realidad es un tipo algo diferente.
Como dicen los documentos 3.1 :
Los objetos de rango tienen muy poco comportamiento: solo admiten indexación, 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 collections.abc.Sequence
con la misma semántica que a 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 index
y los count
métodos y el in
operador (el tiempo que pasa únicamente se enteros). Esto significa que la escritura 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)
regrese True
en 2.6-2.7 y 3.0-3.1 es un error que se corrigió en 3.2 y no se soportó.
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 (Lazy Evaluation).
Para el bucle, esto es ligeramente más rápido que range () y más eficiente en memoria.
>>> b = xrange(5)
>>> b
xrange(5)
xrange()
No es un generador. xrange(n)
.__ iter __ () `es.
Al probar el rango contra xrange en un bucle (sé que debería usar timeit , pero esto fue rápidamente pirateado de la memoria usando un simple ejemplo de comprensión de lista) 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 :-)
xrange
parecía un poco más rápido, aunque con Python 3 la comparación ahora es redundante.
timeit
sirve. Se encarga de ejecutar muchas veces, deshabilitar GC, usar el mejor reloj en lugar de time
, etc.
xrange () y range () en python funcionan de manera similar para el usuario, pero la diferencia viene 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 no. de variables a generar.
xrange () por otro lado genera solo un valor particular a la vez y solo puede usarse con el bucle for para imprimir todos los valores requeridos.
range genera la lista completa y la devuelve. xrange no: genera los números en la lista a pedido.
¿Qué?
range
devuelve una lista estática en tiempo de ejecución.
xrange
devuelve unobject
(que actúa como un generador, aunque ciertamente no es uno) a partir del cual se generan valores cuando sea necesario.
¿Cuándo usar cuál?
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.range
si desea recorrer la lista varias veces.PD: Python 3.x range
función de Python 2.x == xrange
función.
xrange
no devuelve un objeto generador.
Todos lo han 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. Luego, ejecuté 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 ()'.
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 "<stdin>", line 1, in <module>
NameError: name 'xrange' is not defined
La diferencia es aparente. En Python 2.x, range
devuelve una lista,xrange
devuelve un objeto xrange que es iterable.
En Python 3.x, se range
convierte xrange
en Python 2.x, y xrange
se elimina.
En un requisito para escanear / imprimir elementos 0-N, el rango y el rango x funcionan de la siguiente manera.
range (): crea una nueva lista en la memoria y toma todo el 0 a N elementos (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 actual encontrado en la memoria, por lo tanto, utiliza la misma cantidad de memoria todo el tiempo.
En caso de que el elemento requerido esté algo al principio de la lista solo entonces ahorra una buena cantidad de tiempo y memoria.
xrange
no crea una instancia de iterador. Crea un xrange
objeto, que es iterable, pero no un iterador, casi (pero no del todo) una secuencia, como una lista.
El rango 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 caso de usar el rango, todos los elementos se generan a la vez y están disponibles en la memoria.
La diferencia disminuye para argumentos más pequeños para 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.
range: -range completará 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 desea usarlo para loop.so memoria eficiente.
Además, si hacer list(xrange(...))
será equivalente arange(...)
.
Entonces list
es lento.
también xrange
realmente no termina completamente la secuencia
Por eso no es una lista, es un xrange
objeto
range()
en Python 2.x
Esta función es esencialmente la range()
función anterior que estaba disponible en Python 2.x
y devuelve una instancia de un list
objeto que contiene los elementos en el rango especificado.
Sin embargo, esta implementación es demasiado ineficiente cuando se trata de inicializar una lista con un rango de números. Por ejemplo, for i in range(1000000)
sería un comando muy costoso de ejecutar, tanto en términos de memoria como de uso de tiempo, ya que requiere el almacenamiento de esta lista en la memoria.
range()
en Python 3.x
y xrange()
en Python2.x
Python 3.x
introdujo una implementación más nueva de range()
(mientras que la implementación más nueva ya estaba disponible en Python a 2.x
través dexrange()
función).
El range()
explota una estrategia conocida como evaluación perezosa. En lugar de crear una gran lista de elementos dentro del rango, la implementación más reciente introduce la clase range
, un objeto liviano que representa los elementos requeridos en el rango dado, sin almacenarlos explícitamente en la memoria (esto puede sonar como generadores, pero el concepto de evaluación diferida es diferente).
Como ejemplo, considere lo siguiente:
# Python 2.x
>>> a = range(10)
>>> type(a)
<type 'list'>
>>> b = xrange(10)
>>> type(b)
<type 'xrange'>
y
# Python 3.x
>>> a = range(10)
>>> type(a)
<class 'range'>
Ver esta publicación para encontrar la diferencia entre rango y xrange:
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 xrange" , que actúa mucho como un iterador
xrange
No es un iterador. La lista devuelta por range
admite la iteración (una lista es prácticamente el ejemplo prototípico de un iterable). El beneficio general de xrange
no es "mínimo". Y así.