¿Llamar a la función int () en cada elemento de la lista?

184

Tengo una lista con cadenas numéricas, así:

numbers = ['1', '5', '10', '8'];

Me gustaría convertir cada elemento de la lista a entero, por lo que se vería así:

numbers = [1, 5, 10, 8];

Podría hacerlo usando un bucle, así:

new_numbers = [];
for n in numbers:
    new_numbers.append(int(n));
numbers = new_numbers;

¿Tiene que ser tan feo? Estoy seguro de que hay una manera más pitónica de hacer esto en una línea de código. Por favor, ayúdame.

Luz plateada
fuente
1
¿Qué versión de Python estás usando?
Mark Byers

Respuestas:

358

Para eso están las comprensiones de listas :

numbers = [ int(x) for x in numbers ]
adamk
fuente
44
Me muestra una sintaxis no válida
Bugs Buggy
131

En Python 2.x otro enfoque es usar map:

numbers = map(int, numbers)

Nota: en Python 3.x mapdevuelve un objeto de mapa que puede convertir a una lista si lo desea:

numbers = list(map(int, numbers))
Mark Byers
fuente
11
En Python 3.x, mapdevuelve un iterador en lugar de una lista, por lo que debe escribirse como list(map(int, numbers))si se necesitara una lista.
kennytm
2
Creo que actualmente el enfoque de comprensión de la lista es un poco más favorecido.
extraneon
3
@extraneon: Sí ... o tal vez considere usar un generador en lugar de una lista, dependiendo de para qué lo usará. La ventaja de un generador es que si no necesita mirar todos los elementos, no tendrá que perder el tiempo calculando por adelantado.
Mark Byers
44
Medido con timeit bajo Python 2.7.2: LC: 3.578153133392334, mapa: 4.9065070152282715
AJJ
1
@AJJ: maptiene una sobrecarga de configuración más alta, pero en el intérprete de referencia, si la función de transformación es una función incorporada de Python implementada en C, tiene un costo por artículo más bajo. Las pruebas en una entrada de solo cuatro valores no proporcionarán información útil sobre la escala. Dicho esto, en mis propias pruebas (en Py2.7.12 y Py3.5.2, esta última con list()envoltura), Py2 mapganó incluso para entradas de cuatro elementos, y pierde solo por un pequeño margen en Py3; Sospecho que sus pruebas fueron deformadas a favor de listcomps.
ShadowRanger
21

solo un punto

numbers = [int(x) for x in numbers]

la comprensión de la lista es más natural, mientras que

numbers = map(int, numbers)

es más rápido.

Probablemente esto no importará en la mayoría de los casos

Lectura útil: LP vs mapa

renatopp
fuente
66
¿No debería ser number = map (int, number)?
Karan
9

Si tiene la intención de pasar esos enteros a una función o método, considere este ejemplo:

sum(int(x) for x in numbers)

Esta construcción es intencionalmente notablemente similar a las comprensiones de listas mencionadas por adamk. Sin los corchetes, se llama una expresión generadora , y es una forma muy eficiente en la memoria de pasar una lista de argumentos a un método. Una buena discusión está disponible aquí: Expresiones del generador vs. Comprensión de la lista

Tim McNamara
fuente
4

Otra forma de hacerlo en Python 3:

numbers = [*map(int, numbers)]

zhukovgreen
fuente
1
¿Puede explicar esto? No estoy familiarizado con esa sintaxis. ¡Gracias!
abalter
1
Estoy usando la lista de argumentos de desempaquetado ( docs.python.org/3/tutorial/… )
zhukovgreen
Ajá, una cosa de Python 3. Parece extraño haber []tomado una lista de argumentos. Y, no sabía que podría pasar un iterador como una lista de argumentos. Hubiera pensado hacer number = list(map(int, numbers)). Pero gracias por la explicación!
abalter
3

De otra manera,

for i, v in enumerate(numbers): numbers[i] = int(v)
Nick Dandoulakis
fuente
66
OP dijo pitón
SilentGhost
3
De esta manera es muy útil si desea ejecutar la operación solo en algunos de los elementos de la lista. Esto no es relevante para la pregunta en este hilo, pero puede haber casos en los que sea útil
Dikla
1

Pensé en consolidar las respuestas y mostrar algunos timeitresultados.

Python 2 apesta bastante mal en esto, pero mapes un poco más rápido que la comprensión.

Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:42:59) [MSC v.1500 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> setup = """import random
random.seed(10)
l = [str(random.randint(0, 99)) for i in range(100)]"""
>>> timeit.timeit('[int(v) for v in l]', setup)
116.25092001434314
>>> timeit.timeit('map(int, l)', setup)
106.66044823117454

Python 3 es 4 veces más rápido por sí mismo, pero convertir el mapobjeto generador en una lista es aún más rápido que la comprensión, y crear la lista desempacando el mapgenerador (¡gracias Artem!) Es aún más rápido.

Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> setup = """import random
random.seed(10)
l = [str(random.randint(0, 99)) for i in range(100)]"""
>>> timeit.timeit('[int(v) for v in l]', setup)
25.133059591551955
>>> timeit.timeit('list(map(int, l))', setup)
19.705547827217515
>>> timeit.timeit('[*map(int, l)]', setup)
19.45838406513076

Nota: En Python 3, 4 elementos parecen ser el punto de cruce (3 en Python 2) donde la comprensión es un poco más rápida, aunque desempacar el generador es aún más rápido que cualquiera de las listas con más de 1 elemento.

Jim
fuente