Python 3 convierte el rango en una lista

178

Estoy tratando de hacer una lista con números 1-1000. Obviamente, esto sería molesto para escribir / leer, así que estoy tratando de hacer una lista con un rango. En Python 2 parece que:

some_list = range(1,1000)

hubiera funcionado, pero en Python 3 el rango es similar al xrangede Python 2?

¿Alguien puede dar alguna idea de esto?

Cobertizo
fuente
1
Además, some_list[i] == i+1entonces probablemente no necesites una lista de todos modos.
njzk2
1
@RikPoggi. por ejemplo, uno podría necesitar proporcionar una lista para una función de trazado. Algunas veces un rango será suficiente, pero un rango no se puede concatenar (es inmutable), por lo que si necesita agregar un valor inicial predeterminado a todas las listas que se están trazando, ese también debe convertirse en una lista.
SherylHohman

Respuestas:

223

Simplemente puede construir una lista desde el objeto de rango:

my_list = list(range(1, 1001))

Así es como lo haces con generadores en python2.x también. Por lo general, probablemente no necesite una lista, ya que puede obtener el valor de my_list[i]más eficientemente ( i + 1), y si solo necesita iterar sobre ella, simplemente puede recurrir a ella range.

También tenga en cuenta que en python2.x, xrangetodavía es indexable 1 . Esto significa que rangeen python3.x también tiene la misma propiedad 2

1print xrange(30)[12] funciona para python2.x

2 La declaración análoga a 1 en python3.x es print(range(30)[12])y también funciona.

mgilson
fuente
44
Definitivamente, este es el camino a seguir, pero un truco: esto no es realmente un "elenco"
jterrace
@jterrace cambió "cast" a "convertir". Tienes razón sobre que no es un elenco ... Realmente no sé cómo llamarlo exactamente.
mgilson
2
Yo diría "construir" o "construir" (o posiblemente "materializar"), ya que no está "convirtiendo" (como tal) un generador en una lista, está creando un nuevo objeto de lista a partir de una fuente de datos que sucede para ser un generador ... (pero supongo que simplemente dividir los pelos y no estar 100% seguro de lo que prefiero de todos modos)
Jon Clements
2
Mi +1 para "construir" ya que es coherente con otros lenguajes OO. El list(arg)se entiende en otros idiomas como llamar a un constructor de la listclase. En realidad, también es el caso de Python. Los debates sobre si el objeto se llena durante la construcción (como en el caso de C ++) o solo durante el primer método llamado automáticamente (como en el __init__()método Python ) no pueden cambiar la idea abstracta básica. Mi opinión es que el constructor de la lista toma el iterador y llena la lista con los valores devueltos .
pepr
2
¿Por qué da un error en jupyter notebook y funciona bien en shell? Error:'range' object is not callable
subtleseeker
34

En Pythons <= 3.4 puede, como otros sugirieron, usar list(range(10))para hacer una lista fuera de un rango (en general, cualquier iterable).

Otra alternativa, introducida en Python 3.5con sus generalizaciones de desempaquetado, es usar *en una lista literal []:

>>> r = range(10)
>>> l = [*r]
>>> print(l)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Aunque esto es equivalente a list(r), es una sintaxis literal y el hecho de que no esté involucrada ninguna llamada a la función le permite ejecutarse más rápido. También tiene menos caracteres, si necesita codificar golf :-)

Dimitris Fasarakis Hilliard
fuente
44
Para que quede claro, aún puede hacerlo en una línea: [*range(10)]funciona bien para cuando no necesita el rangepara ningún propósito que no sea la inicialización list. Nota al margen: mi parte favorita (está bien, en realidad no) de las generalizaciones de desempaquetado es que los sets vacíos ahora tienen una sintaxis literal {*()}o, como lo llamo, el operador mono de un solo ojo. ;-)
ShadowRanger
@ShadowRanger así es como originalmente pensé en escribirlo. Decidí ser un poco más detallado para no confundir a los nuevos usuarios de Python :-)
Dimitris Fasarakis Hilliard
26

en Python 3.x, la range()función tiene su propio tipo. así que en este caso debes usar iterador

list(range(1000))

nurulhudamustaqim
fuente
11
"en este caso debes usar el iterador"? ¿Qué diablos se supone que significa eso?
user2357112 es compatible con Monica el
2
Estoy usando python 3.7 y probé x = list (range (1000)) pero recibí el error TypeError: el objeto 'list' no es invocable
Earthshaker
@Earthshaker Debes tener un error tipográfico, comolist(range(1000))()
wjandrea
17

La razón por la cual Python3 carece de una función para obtener directamente una lista a distancia es porque el diseñador original de Python3 era bastante novato en Python2. Solo consideró el uso de la range()función en un bucle for, por lo tanto, la lista nunca debería necesitar expandirse. De hecho, muy a menudo necesitamos usar la range()función para producir una lista y pasarla a una función.

Por lo tanto, en este caso, Python3 es menos conveniente en comparación con Python2 porque:

  • En Python2, tenemos xrange()y range();
  • En Python3, tenemos range()ylist(range())

No obstante, aún puede usar la expansión de lista de esta manera:

[*range(N)]
xuancong84
fuente
3
El punto es hacer que sea menos conveniente hacer un list, porque eso generalmente es lo incorrecto. Para 99 de cada 100 casos de uso, hacer un real listes ineficiente y sin sentido, ya que en rangesí mismo actúa como una secuencia inmutable en casi todos los sentidos, a veces más eficientemente para arrancar (por ejemplo, pruebas de contención para ints are O(1), vs. O(n)for lists). En Python 2, la gente solía usar rangede forma predeterminada, aunque xrangecasi siempre era la mejor opción; en Python 3, puede optar explícitamente por el list, no obtenerlo por accidente usando el nombre incorrecto.
ShadowRanger
77
El comentario sobre el diseñador de Python 3 y su experiencia en Python 2 es bastante audaz e impertinente.
kazarey
@kazarey ¿Pero es verdad? Hay muchas cosas en Python que son cuestionables en este sentido
javadba
1
Votaría, especialmente por la taquigrafía de desempaque para construir la lista, pero estoy de acuerdo con @kazarey. El comentario sobre el diseñador es infundado (o al menos no respaldado por referencias) e innecesario.
Nubarke
12

Realmente no debería necesitar usar los números 1-1000 en una lista. Pero si por alguna razón realmente necesita estos números, entonces podría hacer:

[i for i in range(1, 1001)]

Lista de comprensión en pocas palabras:

La comprensión de la lista anterior se traduce en:

nums = []
for i in range(1, 1001):
    nums.append(i)

Esta es solo la sintaxis de comprensión de la lista, aunque de 2.x. Sé que esto funcionará en Python 3, pero no estoy seguro de si también hay una sintaxis actualizada

El rango comienza incluyendo el primer parámetro; pero termina Hasta, sin incluir el segundo parámetro (cuando se proporcionan 2 parámetros; si el primer parámetro se deja, comenzará en '0')

range(start, end+1)
[start, start+1, .., end]
inspectorG4dget
fuente
20
¿Por qué la comprensión? Solo:list(range(1000))
Rik Poggi
¡Gracias! ¿Te importaría explicar por qué es i for i in ... en lugar de simplemente for i in?
Boathouse
No he trabajado con python3. Así que no estoy completamente seguro de cómo funciona. Sé que las comprensiones funcionarán, pero no estaba al 100% en el casting. Pero si el casting funciona, entonces tienes razón y tu camino es más pitónico.
inspectorG4dget
1
@ inspectorG4dget: No es "casting", está llamando al list()constructor con un iterable . El list()constructor sabe cómo crear una nueva lista cuando se le da un objeto iterable.
Greg Hewgill
44
@ inspectorG4dget: list(range(1000))funcionará en python3 al igual que list(xrange(1000))en python2
Rik Poggi
4

En realidad, si desea 1-1000 (inclusive), use la range(...)función con los parámetros 1 y 1001: range(1, 1001)porque la range(start, end)función va de inicio a (fin-1), inclusive.

Computadora cósmica
fuente
0

Use Range en Python 3.

Aquí hay una función de ejemplo que regresa entre números de dos números

def get_between_numbers(a, b):
    """
    This function will return in between numbers from two numbers.
    :param a:
    :param b:
    :return:
    """
    x = []
    if b < a:
        x.extend(range(b, a))
        x.append(a)
    else:
        x.extend(range(a, b))
        x.append(b)

    return x

Resultado

print(get_between_numbers(5, 9))
print(get_between_numbers(9, 5))

[5, 6, 7, 8, 9]  
[5, 6, 7, 8, 9]
Rajiv Sharma
fuente
Esto parece estar respondiendo una pregunta diferente ...?
wjandrea
-1

De hecho, esta es una retrogradación de Python3 en comparación con Python2. Ciertamente, Python2 que usa range () y xrange () es más conveniente que Python3 que usa list (range ()) y range () respectivamente. La razón es que el diseñador original de Python3 no tiene mucha experiencia, solo consideraron el uso de la función de rango por parte de muchos principiantes para iterar sobre una gran cantidad de elementos donde la memoria y la CPU son ineficientes; pero descuidaron el uso de la función de rango para producir una lista de números. Ahora, ya es demasiado tarde para que vuelvan a cambiar.

Si fuera el diseñador de Python3, haría lo siguiente:

  1. use irange para devolver un iterador de secuencia
  2. use lrange para devolver una lista de secuencia
  3. use range para devolver un iterador de secuencia (si el número de elementos es grande, por ejemplo, range (9999999) o una lista de secuencia (si el número de elementos es pequeño, por ejemplo, range (10))

Eso debería ser óptimo.

xuancong84
fuente
¿Cómo responde esto a la pregunta?
wjandrea
Sí, responde la pregunta solicitando a los desarrolladores de Python3 que cambien y mejoren Python3. Pero es poco probable que cambien, ya que no son tan elegantes.
xuancong84