¿Range () realmente crea listas?

Tanto mi profesor como este tipo afirman que el range crea una lista de valores.

“Nota: la función de rango simplemente devuelve una lista que contiene los números de x a y-1. Por ejemplo, el rango (5, 10) devuelve la lista [5, 6, 7, 8, 9]”.

Creo que esto debe ser inexacto porque:

 type(range(5, 10))  

Además, la única forma aparente de acceder a los enteros creados por el range es iterarlos, lo que me lleva a creer que el range etiquetado como una lista es incorrecto.

En Python 2.x, el range devuelve una lista, pero en Python 3.x el range devuelve una secuencia inmutable, de range de tipo.

Python 2.x:

 >>> type(range(10))  >>> type(xrange(10))  

Python 3.x:

 >>> type(range(10))  

En Python 2.x, si desea obtener un objeto iterable, como en Python 3.x, puede usar la función xrange , que devuelve una secuencia inmutable de tipo xrange .

Ventaja de xrange sobre el range en Python 2.x:

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 ruptura).

Nota:

Además, la única forma aparente de acceder a los enteros creados por range() es iterar a través de ellos,

No Dado que los objetos de range en Python 3 son secuencias inmutables, también admiten la indexación. Citando desde la documentación de la función de range ,

Los rangos implementan todas las operaciones de secuencia comunes excepto la concatenación y la repetición

Los objetos de rango implementan collections.abc.Sequence ABC y proporcionan características como pruebas de contención, búsqueda de índice de elementos , segmentación y soporte para índices negativos.

Por ejemplo,

 >>> range(10, 20)[5] 15 >>> range(10, 20)[2:5] range(12, 15) >>> list(range(10, 20)[2:5]) [12, 13, 14] >>> list(range(10, 20, 2)) [10, 12, 14, 16, 18] >>> 18 in range(10, 20) True >>> 100 in range(10, 20) False 

Todo esto es posible con esa secuencia de range inmutable.


Recientemente, enfrenté un problema y creo que sería apropiado incluirlo aquí. Considera este código Python 3.x

 from itertools import islice numbers = range(100) items = list(islice(numbers, 10)) while items: items = list(islice(numbers, 10)) print(items) 

Uno esperaría que este código se imprima cada diez números como una lista, hasta el 99. Pero, se ejecutaría infinitamente. ¿Puedes razonar por qué?

Solución

Porque el range devuelve una secuencia inmutable, no un objeto iterador. Por lo tanto, cada islice se realiza un islice en un objeto de range , siempre comienza desde el principio. Piense en ello como un reemplazo directo para una lista inmutable. Ahora viene la pregunta, ¿cómo lo arreglarás? Es simple, solo tienes que sacar un iterador. Simplemente cambia

numbers = range(100)

a

numbers = iter(range(100))

Ahora, los numbers son un objeto iterador y recuerdan cuánto tiempo se ha repetido antes. Entonces, cuando el islice itera, simplemente comienza desde el lugar donde terminó anteriormente.

Depende.

En python-2.x, el range crea realmente una lista (que también es una secuencia), mientras que xrange crea un objeto xrange que se puede usar para iterar a través de los valores.

Por otro lado, en python-3.x, el range crea un iterable (o más específicamente, una secuencia)

range crea una lista si la versión de python utilizada es 2.x. En este escenario, el rango se utilizará solo si se hace referencia más de una vez; de lo contrario, use xrange, que crea un generador allí, al usar el uso de la memoria y, a veces, el tiempo, ya que tiene un enfoque perezoso.

xrange no está allí en python 3.x, más bien el rango representa lo que xrange es para python 2.x

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