not - ¿Cuál es la diferencia entre las funciones de rango y rango en Python 2.X?
xrange is not defined (29)
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 sea más rápido) o qué es lo que, aparte de eso, es diferente
for i in range(0, 20):
for i in xrange(0, 20):
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:
- Puede iterar listas más largas sin obtener un
MemoryError
. - A medida que se resuelve cada número perezosamente, si detiene la iteración anticipadamente, no perderá tiempo creando toda la lista.
el rango crea una lista, por lo que si realiza el
range(1, 10000000)
, crea una lista en la memoria con9999999
elementos.
xrange
es un generador, por lo quees 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.
¿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 los valores se generan cuando es necesario.
¿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.
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
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.
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 :-)
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, 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.
El rango genera la lista completa y la devuelve. xrange no lo hace: genera los números en la lista a pedido.
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 ligeramente más rápido que el rango () y más eficiente en memoria.
>>> b = xrange(5)
>>> b
xrange(5)
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 el total de 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 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, entonces ahorra una buena cantidad de tiempo y memoria.
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 xrange
en Python-3
Feliz codificacion !!
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 ().
Estoy sorprendido de que nadie lea el doc :
Esta función es muy similar a
range()
, pero devuelve un objetoxrange
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 dexrange()
sobre elrange()
es mínima (ya quexrange()
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 conbreak
).
La diferencia disminuye para que los argumentos más pequeños xrange(..)
/ 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.
Lea la siguiente publicación para la comparación entre rango y rango con análisis gráfico.
Mira esta post para encontrar la diferencia entre rango y rango:
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 de rango" , que actúa como un iterador
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 documentación y la función de ayuda:
print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)
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 ()''.
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 de xrange de python
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 quiere usar la memoria de loop.so.
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 usamos el rango (), 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.
xrange devuelve un iterador y solo mantiene un número en la memoria a la vez. El rango mantiene la lista completa de números en la memoria.
xrange utiliza un iterador (genera valores sobre la marcha), el rango devuelve una lista.
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 utiliza 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!
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.
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.
range () vs xrange () en python:
range () y xrange () son dos funciones que se pueden usar para iterar un cierto número de veces en los bucles de Python. En Python 3, no hay xrange, pero la función de rango se comporta como xrange en Python 2. Si desea escribir código que se ejecute tanto en Python 2 como en Python 3, debe usar range ().
range () - Esto devuelve una lista de números creados usando la función range ().
xrange (): esta función devuelve el objeto generador que se puede usar para mostrar números solo en bucle. Solo el rango particular se muestra a pedido y, por lo tanto, se llama "evaluación perezosa".
Ambos se implementan de diferentes maneras y tienen diferentes características asociadas a ellos. Los puntos de comparaciones son:
- Tipo de retorno Memoria Operación Velocidad de uso
- Memoria
- Uso de la operación
- Velocidad
1. Tipo de devolución:
range () devuelve - la lista como tipo de retorno.
xrange () devuelve - objeto 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))
Salida:
The return type of range() is :
<type ''list''>
The return type of xrange() is :
<type ''xrange''>
2. Memoria:
La variable que almacena el rango creado por range () toma más memoria en comparación con la variable que almacena el rango usando xrange (). La razón básica de esto es que el tipo de retorno de range () es list y xrange () es un objeto 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))
Salida:
The size allotted using range() is :
80064
The size allotted using xrange() is :
40
3. Uso de operaciones:
Como range () devuelve la lista, todas las operaciones que se pueden aplicar en la lista se pueden usar en ella. Por otro lado, como xrange () devuelve el objeto xrange, las operaciones asociadas a la lista no se pueden aplicar a ellos, por lo tanto, es una desventaja.
# 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])
Salida:
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. Velocidad:
Debido al hecho de que xrange () evalúa solo el objeto generador que contiene solo los valores requeridos por la evaluación perezosa, por lo tanto, es más rápido en la implementación que en range ().
Puntos importantes :
- Si desea escribir código que se ejecute tanto en Python 2 como en Python 3, use range () ya que la función xrange está obsoleta en Python 3.
- El rango () es más rápido si se itera sobre la misma secuencia varias veces.
- xrange () tiene que reconstruir el objeto entero cada vez, pero el rango () tendrá objetos enteros reales. (Sin embargo, siempre se desempeñará peor en términos de memoria).
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 bucles, esto es ligeramente más rápido que el rango () y más eficiente en memoria. xrange () se opone a 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