¿Alguien puede describir brevemente la diferencia entre los 2 para nosotros los que no somos python? Tal vez algo como "xrange () hace todo rango (), pero también es compatible con X, Y y Z"
Outlaw Programmer
87
range (n) crea una lista que contiene todos los enteros 0..n-1. Esto es un problema si haces rango (1000000), porque terminarás con una lista> 4Mb. xrange se ocupa de esto devolviendo un objeto que pretende ser una lista, pero que solo resuelve el número necesario del índice solicitado y lo devuelve.
Básicamente, mientras que range(1000)es a list, xrange(1000)es un objeto que actúa como a generator(aunque ciertamente no lo es ). Además, xrangees más rápido. Puede import timeit from timeity luego hacer un método que solo tenga for i in xrange: passy otro para range, luego hacer timeit(method1)y timeit(method2)y, he aquí, xrange es casi el doble de rápido a veces (es decir, cuando no necesita una lista). (Para mí, para i in xrange(1000):passvs para i in range(1000):passtomó 13.316725969314575vs 21.190124988555908segundos respectivamente, eso es mucho.)
Para el rendimiento, especialmente cuando está iterando en un amplio rango, xrange()generalmente es mejor. Sin embargo, todavía hay algunos casos por los que podría preferir range():
En python 3, range()hace lo que xrange()solía hacer y xrange()no existe. Si desea escribir código que se ejecutará en Python 2 y Python 3, no puede usarlo xrange().
range()en realidad puede ser más rápido en algunos casos, por ejemplo. si itera sobre la misma secuencia varias veces. xrange()tiene que reconstruir el objeto entero cada vez, pero range()tendrá objetos enteros reales. (Sin embargo, siempre funcionará peor en términos de memoria)
xrange()no es utilizable en todos los casos donde se necesita una lista real. Por ejemplo, no admite cortes, ni ningún método de lista.
[Editar] Hay un par de publicaciones que mencionan cómo range()se actualizará con la herramienta 2to3. Para el registro, aquí está el resultado de ejecutar la herramienta en algunos usos de muestra de range()yxrange()
RefactoringTool:Skipping implicit fixer: buffer
RefactoringTool:Skipping implicit fixer: idioms
RefactoringTool:Skipping implicit fixer: ws_comma
--- range_test.py (original)+++ range_test.py (refactored)@@-1,7+1,7@@for x in range(20):- a=range(20)+ a=list(range(20))
b=list(range(20))
c=[x for x in range(20)]
d=(x for x in range(20))- e=xrange(20)+ e=range(20)
Como puede ver, cuando se usa en un bucle for o comprensión, o cuando ya está envuelto con list (), el rango no se modifica.
¿Qué quieres decir con "el rango se convertirá en un iterador"? ¿No debería ser esto "generador"?
Michael Mior
44
No. Generator se refiere a un tipo específico de iterador, y el nuevo rangeno es un iterador de todos modos.
user2357112 es compatible con Monica
Tu segunda bala realmente no tiene ningún sentido. Estás diciendo que no puedes usar un objeto varias veces; ¡Seguro que puede! intente xr = xrange(1,11)luego en la siguiente línea for i in xr: print " ".join(format(i*j,"3d") for j in xr)y listo! Tienes tus horarios hasta diez. Funciona igual que r = range(1,11)y for i in r: print " ".join(format(i*j,"3d") for j in r)... todo es un objeto en Python2. Creo que lo que querías decir es que puedes hacer una comprensión basada en índices (si eso tiene sentido) mejor rangeen lugar de hacerlo xrange. El rango es útil muy raramente, creo
dylnmc
(Habitación insuficiente) Aunque, yo hago piensan que rangepuede ser útil si desea utilizar una listen un bucle y luego cambiar ciertos índices basados en ciertas condiciones o cosas Anexar a esa lista, entonces rangees definitivamente mejor. Sin embargo, xrangees simplemente más rápido y usa menos memoria, por lo que para la mayoría de las aplicaciones de bucle, parece ser el mejor. Hay casos, volviendo a la pregunta del interrogador, que rara vez existen, donde rangesería mejor. Quizás no tan raramente como estoy pensando, pero ciertamente uso el xrange95% del tiempo.
dylnmc
129
No, ambos tienen sus usos:
Úselo xrange()al iterar, ya que ahorra memoria. Decir:
for x in xrange(1, one_zillion):
más bien que:
for x in range(1, one_zillion):
Por otro lado, úsalo range()si realmente quieres una lista de números.
multiples_of_seven = range(7,100,7)print"Multiples of seven < 100: ", multiples_of_seven
Usted debe favorecer range()más xrange()sólo cuando se necesita una lista real. Por ejemplo, cuando desea modificar la lista devuelta por range(), o cuando desea dividirla. Para la iteración o incluso la indexación normal, xrange()funcionará bien (y generalmente es mucho más eficiente). Hay un punto donde range()es un poco más rápido que xrange()para listas muy pequeñas, pero dependiendo de su hardware y otros detalles, el punto de equilibrio puede ser el resultado de la longitud 1 o 2; No es algo de qué preocuparse. Prefiero xrange().
Otra diferencia es que xrange () no puede admitir números mayores que C ints, por lo que si desea tener un rango utilizando el soporte de números grandes incorporado de Python, debe usar range ().
Python2.7.3(default,Jul132012,22:29:01)[GCC 4.7.1] on linux2
Type"help","copyright","credits"or"license"for more information.>>> range(123456787676676767676676,123456787676676767676679)[123456787676676767676676L,123456787676676767676677L,123456787676676767676678L]>>> xrange(123456787676676767676676,123456787676676767676679)Traceback(most recent call last):File"<stdin>", line 1,in<module>OverflowError:Python int too large to convert to C long
Python 3 no tiene este problema:
Python3.2.3(default,Jul142012,01:01:48)[GCC 4.7.1] on linux2
Type"help","copyright","credits"or"license"for more information.>>> range(123456787676676767676676,123456787676676767676679)
range(123456787676676767676676,123456787676676767676679)
xrange()es más eficiente porque en lugar de generar una lista de objetos, solo genera un objeto a la vez. En lugar de 100 enteros, y todos sus gastos generales, y la lista para colocarlos, solo tiene un entero a la vez. Generación más rápida, mejor uso de memoria, código más eficiente.
A menos que necesite específicamente una lista para algo, siempre estoy a favor xrange()
range () devuelve una lista, xrange () devuelve un objeto xrange.
xrange () es un poco más rápido y un poco más eficiente en memoria. Pero la ganancia no es muy grande.
La memoria extra utilizada por una lista, por supuesto, no solo se desperdicia, las listas tienen más funcionalidad (división, repetición, inserción, ...). Las diferencias exactas se pueden encontrar en la documentación . No hay una regla estricta, use lo que se necesita.
Python 3.0 todavía está en desarrollo, pero IIRC range () será muy similar a xrange () de 2.X y list (range ()) puede usarse para generar listas.
Solo me gustaría decir que REALMENTE no es tan difícil obtener un objeto xrange con funcionalidad de corte e indexación. He escrito un código que funciona bastante bien y es tan rápido como xrange para cuando cuenta (iteraciones).
from __future__ import division
def read_xrange(xrange_object):# returns the xrange object's start, stop, and step
start = xrange_object[0]if len(xrange_object)>1:
step = xrange_object[1]- xrange_object[0]else:
step =1
stop = xrange_object[-1]+ step
return start, stop, step
classXrange(object):''' creates an xrange-like object that supports slicing and indexing.
ex: a = Xrange(20)
a.index(10)
will work
Also a[:5]
will return another Xrange object with the specified attributes
Also allows for the conversion from an existing xrange object
'''def __init__(self,*inputs):# allow inputs of xrange objectsif len(inputs)==1:
test,= inputs
if type(test)== xrange:
self.xrange = test
self.start, self.stop, self.step = read_xrange(test)return# or create one from start, stop, step
self.start, self.step =0,Noneif len(inputs)==1:
self.stop,= inputs
elif len(inputs)==2:
self.start, self.stop = inputs
elif len(inputs)==3:
self.start, self.stop, self.step = inputs
else:raiseValueError(inputs)
self.xrange = xrange(self.start, self.stop, self.step)def __iter__(self):return iter(self.xrange)def __getitem__(self, item):if type(item)is int:if item <0:
item += len(self)return self.xrange[item]if type(item)is slice:# get the indexes, and then convert to the number
start, stop, step = item.start, item.stop, item.step
start = start if start !=Noneelse0# convert start = None to start = 0if start <0:
start += start
start = self[start]if start <0:raiseIndexError(item)
step =(self.step if self.step !=Noneelse1)*(step if step !=Noneelse1)
stop = stop if stop isnotNoneelse self.xrange[-1]if stop <0:
stop += stop
stop = self[stop]
stop = stop
if stop > self.stop:raiseIndexErrorif start < self.start:raiseIndexErrorreturnXrange(start, stop, step)def index(self, value):
error =ValueError('object.index({0}): {0} not in object'.format(value))
index =(value - self.start)/self.step
if index %1!=0:raise error
index = int(index)try:
self.xrange[index]except(IndexError,TypeError):raise error
return index
def __len__(self):return len(self.xrange)
Honestamente, creo que todo el asunto es un poco tonto y xrange debería hacer todo esto de todos modos ...
Sí de acuerdo; desde una tecnología totalmente diferente, verifique el trabajo en lodash para hacerlo perezoso: github.com/lodash/lodash/issues/274 . Rebanar, etc., aún debe ser lo más flojo posible y, cuando no, solo reificar.
Rob Grant
4
Un buen ejemplo dado en el libro: Practical Python Por Magnus Lie Hetland
No recomendaría usar range en lugar de xrange en el ejemplo anterior, aunque solo se necesitan los primeros cinco números, range calcula todos los números, y eso puede llevar mucho tiempo. Con xrange, esto no es un problema porque calcula solo los números necesarios.
Sí, leí la respuesta de @ Brian: en python 3, range () es un generador de todos modos y xrange () no existe.
No hagas esto. xrange () desaparecerá, pero también muchas otras cosas. La herramienta que usará para traducir su código Python 2.x al código Python 3.x traducirá automáticamente xrange () a range (), pero range () se traducirá a la lista menos eficiente (range ()).
Thomas Wouters el
10
Thomas: En realidad es un poco más inteligente que eso. Traducirá range () en situaciones en las que claramente no necesita una lista real (por ejemplo, en un bucle for, o comprensión) a simplemente range (). Solo los casos en los que se asigna a una variable o se usa directamente se deben envolver con list ()
Brian
2
De acuerdo, todos aquí tienen una opinión diferente sobre las ventajas y desventajas de xrange versus range. En su mayoría son correctos, xrange es un iterador, y el rango se desarrolla y crea una lista real. Para la mayoría de los casos, realmente no notará una diferencia entre los dos. (Puede usar el mapa con rango pero no con xrange, pero usa más memoria).
Sin embargo, lo que creo que quieres escuchar es que la opción preferida es xrange. Dado que range en Python 3 es un iterador, la herramienta de conversión de código 2to3 convertirá correctamente todos los usos de xrange en range, y arrojará un error o advertencia para los usos de range. Si desea asegurarse de convertir fácilmente su código en el futuro, usará solo xrange y list (xrange) cuando esté seguro de que desea una lista. Aprendí esto durante el sprint CPython en PyCon este año (2008) en Chicago.
Eso no es cierto. El código como "para x en el rango (20)" se dejará como rango, y el código como "x = rango (20)" se convertirá en "x = lista (rango (20))" - sin errores. Además, si desea escribir código que se ejecutará tanto en 2.6 como en 3.0, range () es su única opción sin agregar funciones de compatibilidad.
Brian
2
range(): range(1, 10)devuelve una lista de 1 a 10 números y mantiene toda la lista en la memoria.
xrange(): Me gusta range(), pero en lugar de devolver una lista, devuelve un objeto que genera los números en el rango bajo demanda. Para el bucle, esto es ligeramente más rápido range()y más eficiente en memoria. xrange()objeto como un iterador y genera los números a pedido (evaluación diferida).
range()hace lo mismo que xrange()solía hacer en Python 3 y no existe ningún término xrange()en Python 3. en
range()realidad puede ser más rápido en algún escenario si itera sobre la misma secuencia varias veces. xrange()tiene que reconstruir el objeto entero cada vez, pero range()tendrá objetos enteros reales.
Si bien xrangees más rápido que rangeen la mayoría de las circunstancias, la diferencia en el rendimiento es bastante mínima. El pequeño programa a continuación compara la iteración sobre ay rangean xrange:
import timeit
# Try various list sizes.for list_len in[1,10,100,1000,10000,100000,1000000]:# Time doing a range and an xrange.
rtime = timeit.timeit('a=0;\nfor n in range(%d): a += n'%list_len, number=1000)
xrtime = timeit.timeit('a=0;\nfor n in xrange(%d): a += n'%list_len, number=1000)# Print the resultprint"Loop list of len %d: range=%.4f, xrange=%.4f"%(list_len, rtime, xrtime)
Los resultados a continuación muestran que, de xrangehecho, es más rápido, pero no lo suficiente como para sudar.
Loop list of len 1: range=0.0003, xrange=0.0003Loop list of len 10: range=0.0013, xrange=0.0011Loop list of len 100: range=0.0068, xrange=0.0034Loop list of len 1000: range=0.0609, xrange=0.0438Loop list of len 10000: range=0.5527, xrange=0.5266Loop list of len 100000: range=10.1666, xrange=7.8481Loop list of len 1000000: range=168.3425, xrange=155.8719
Así que, por supuesto xrange, use , pero a menos que esté en un hardware restringido, no se preocupe demasiado por eso.
range(1000)
es alist
,xrange(1000)
es un objeto que actúa como agenerator
(aunque ciertamente no lo es ). Además,xrange
es más rápido. Puedeimport timeit from timeit
y luego hacer un método que solo tengafor i in xrange: pass
y otro pararange
, luego hacertimeit(method1)
ytimeit(method2)
y, he aquí, xrange es casi el doble de rápido a veces (es decir, cuando no necesita una lista). (Para mí, parai in xrange(1000):pass
vs parai in range(1000):pass
tomó13.316725969314575
vs21.190124988555908
segundos respectivamente, eso es mucho.)xrange(100)
como 20% más rápido querange(100)
.Respuestas:
Para el rendimiento, especialmente cuando está iterando en un amplio rango,
xrange()
generalmente es mejor. Sin embargo, todavía hay algunos casos por los que podría preferirrange()
:En python 3,
range()
hace lo quexrange()
solía hacer yxrange()
no existe. Si desea escribir código que se ejecutará en Python 2 y Python 3, no puede usarloxrange()
.range()
en realidad puede ser más rápido en algunos casos, por ejemplo. si itera sobre la misma secuencia varias veces.xrange()
tiene que reconstruir el objeto entero cada vez, perorange()
tendrá objetos enteros reales. (Sin embargo, siempre funcionará peor en términos de memoria)xrange()
no es utilizable en todos los casos donde se necesita una lista real. Por ejemplo, no admite cortes, ni ningún método de lista.[Editar] Hay un par de publicaciones que mencionan cómo
range()
se actualizará con la herramienta 2to3. Para el registro, aquí está el resultado de ejecutar la herramienta en algunos usos de muestra derange()
yxrange()
Como puede ver, cuando se usa en un bucle for o comprensión, o cuando ya está envuelto con list (), el rango no se modifica.
fuente
range
no es un iterador de todos modos.xr = xrange(1,11)
luego en la siguiente líneafor i in xr: print " ".join(format(i*j,"3d") for j in xr)
y listo! Tienes tus horarios hasta diez. Funciona igual quer = range(1,11)
yfor i in r: print " ".join(format(i*j,"3d") for j in r)
... todo es un objeto en Python2. Creo que lo que querías decir es que puedes hacer una comprensión basada en índices (si eso tiene sentido) mejorrange
en lugar de hacerloxrange
. El rango es útil muy raramente, creorange
puede ser útil si desea utilizar unalist
en un bucle y luego cambiar ciertos índices basados en ciertas condiciones o cosas Anexar a esa lista, entoncesrange
es definitivamente mejor. Sin embargo,xrange
es simplemente más rápido y usa menos memoria, por lo que para la mayoría de las aplicaciones de bucle, parece ser el mejor. Hay casos, volviendo a la pregunta del interrogador, que rara vez existen, donderange
sería mejor. Quizás no tan raramente como estoy pensando, pero ciertamente uso elxrange
95% del tiempo.No, ambos tienen sus usos:
Úselo
xrange()
al iterar, ya que ahorra memoria. Decir:más bien que:
Por otro lado, úsalo
range()
si realmente quieres una lista de números.fuente
Usted debe favorecer
range()
másxrange()
sólo cuando se necesita una lista real. Por ejemplo, cuando desea modificar la lista devuelta porrange()
, o cuando desea dividirla. Para la iteración o incluso la indexación normal,xrange()
funcionará bien (y generalmente es mucho más eficiente). Hay un punto donderange()
es un poco más rápido quexrange()
para listas muy pequeñas, pero dependiendo de su hardware y otros detalles, el punto de equilibrio puede ser el resultado de la longitud 1 o 2; No es algo de qué preocuparse. Prefieroxrange()
.fuente
Otra diferencia es que xrange () no puede admitir números mayores que C ints, por lo que si desea tener un rango utilizando el soporte de números grandes incorporado de Python, debe usar range ().
Python 3 no tiene este problema:
fuente
xrange()
es más eficiente porque en lugar de generar una lista de objetos, solo genera un objeto a la vez. En lugar de 100 enteros, y todos sus gastos generales, y la lista para colocarlos, solo tiene un entero a la vez. Generación más rápida, mejor uso de memoria, código más eficiente.A menos que necesite específicamente una lista para algo, siempre estoy a favor
xrange()
fuente
range () devuelve una lista, xrange () devuelve un objeto xrange.
xrange () es un poco más rápido y un poco más eficiente en memoria. Pero la ganancia no es muy grande.
La memoria extra utilizada por una lista, por supuesto, no solo se desperdicia, las listas tienen más funcionalidad (división, repetición, inserción, ...). Las diferencias exactas se pueden encontrar en la documentación . No hay una regla estricta, use lo que se necesita.
Python 3.0 todavía está en desarrollo, pero IIRC range () será muy similar a xrange () de 2.X y list (range ()) puede usarse para generar listas.
fuente
Solo me gustaría decir que REALMENTE no es tan difícil obtener un objeto xrange con funcionalidad de corte e indexación. He escrito un código que funciona bastante bien y es tan rápido como xrange para cuando cuenta (iteraciones).
Honestamente, creo que todo el asunto es un poco tonto y xrange debería hacer todo esto de todos modos ...
fuente
Un buen ejemplo dado en el libro: Practical Python Por Magnus Lie Hetland
No recomendaría usar range en lugar de xrange en el ejemplo anterior, aunque solo se necesitan los primeros cinco números, range calcula todos los números, y eso puede llevar mucho tiempo. Con xrange, esto no es un problema porque calcula solo los números necesarios.
Sí, leí la respuesta de @ Brian: en python 3, range () es un generador de todos modos y xrange () no existe.
fuente
Ir con rango por estas razones:
1) xrange desaparecerá en las nuevas versiones de Python. Esto le brinda compatibilidad futura fácil.
2) el rango tomará las eficiencias asociadas con xrange.
fuente
De acuerdo, todos aquí tienen una opinión diferente sobre las ventajas y desventajas de xrange versus range. En su mayoría son correctos, xrange es un iterador, y el rango se desarrolla y crea una lista real. Para la mayoría de los casos, realmente no notará una diferencia entre los dos. (Puede usar el mapa con rango pero no con xrange, pero usa más memoria).
Sin embargo, lo que creo que quieres escuchar es que la opción preferida es xrange. Dado que range en Python 3 es un iterador, la herramienta de conversión de código 2to3 convertirá correctamente todos los usos de xrange en range, y arrojará un error o advertencia para los usos de range. Si desea asegurarse de convertir fácilmente su código en el futuro, usará solo xrange y list (xrange) cuando esté seguro de que desea una lista. Aprendí esto durante el sprint CPython en PyCon este año (2008) en Chicago.
fuente
range()
:range(1, 10)
devuelve una lista de 1 a 10 números y mantiene toda la lista en la memoria.xrange()
: Me gustarange()
, pero en lugar de devolver una lista, devuelve un objeto que genera los números en el rango bajo demanda. Para el bucle, esto es ligeramente más rápidorange()
y más eficiente en memoria.xrange()
objeto como un iterador y genera los números a pedido (evaluación diferida).range()
hace lo mismo quexrange()
solía hacer en Python 3 y no existe ningún términoxrange()
en Python 3. enrange()
realidad puede ser más rápido en algún escenario si itera sobre la misma secuencia varias veces.xrange()
tiene que reconstruir el objeto entero cada vez, perorange()
tendrá objetos enteros reales.fuente
Si bien
xrange
es más rápido querange
en la mayoría de las circunstancias, la diferencia en el rendimiento es bastante mínima. El pequeño programa a continuación compara la iteración sobre ayrange
anxrange
:Los resultados a continuación muestran que, de
xrange
hecho, es más rápido, pero no lo suficiente como para sudar.Así que, por supuesto
xrange
, use , pero a menos que esté en un hardware restringido, no se preocupe demasiado por eso.fuente
list_len
se está utilizando y, por lo tanto, solo está ejecutando este código para listas de longitud 100.rtime = timeit.timeit('a=0;\nfor n in range(%d): a += n' % list_len, number=1000)