Chamar a função int () em todos os elementos da lista?

184

Eu tenho uma lista com seqüências numéricas, assim:

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

Gostaria de converter todos os elementos da lista em números inteiros, assim ficaria assim:

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

Eu poderia fazer isso usando um loop, assim:

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

Tem que ser tão feio? Tenho certeza de que há uma maneira mais pitônica de fazer isso em uma linha de código. Por favor, me ajude.

Luz cinza
fonte
1
Qual versão do Python você está usando?
Mark Byers

Respostas:

358

É para isso que servem as compreensões de lista :

numbers = [ int(x) for x in numbers ]
adamk
fonte
4
Shows de sintaxe inválida para mim
Erros Buggy
131

No Python 2.x, outra abordagem é usar map:

numbers = map(int, numbers)

Nota: no Python 3.x mapretorna um objeto de mapa que você pode converter em uma lista, se desejar:

numbers = list(map(int, numbers))
Mark Byers
fonte
11
No Python 3.x, mapretorna um iterador em vez de uma lista, portanto, ele precisa ser escrito como list(map(int, numbers))se fosse necessária uma lista.
Kennytm
2
Acho que atualmente a abordagem de compreensão da lista é um pouco mais favorecida.
Extraneon
3
@extraneon: Sim ... ou talvez considere usar um gerador em vez de uma lista, dependendo do que você usará. A vantagem de um gerador é que, se você não precisar examinar todos os elementos, não precisará perder tempo calculando-os com antecedência.
Mark Byers
4
Medido com timeit sob Python 2.7.2: LC: 3,578153133392334, mapa: 4,9065070152282715
AJJ
1
@AJJ: mappossui uma sobrecarga de configuração mais alta, mas no interpretador de referência, se a função de transformação for uma função interna do Python implementada em C, ela terá um custo menor por item. Testar em uma entrada de apenas quatro valores não fornecerá informações úteis sobre dimensionamento. Dito isto, em meus próprios testes (no Py2.7.12 e Py3.5.2, o último com list()quebra automática), o Py2 mapvenceu até por quatro entradas de elementos e perde apenas uma pequena margem no Py3; Eu suspeito que seus testes foram distorcidos em favor dos listcomps.
ShadowRanger 8/16
21

apenas um ponto

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

a compreensão da lista é mais natural, enquanto

numbers = map(int, numbers)

é mais rápido.

Provavelmente isso não importa na maioria dos casos

Leitura útil: LP vs map

renatopp
fonte
6
Não deveria ser number = map (int, number)?
Karan
9

Se você pretende passar esses números inteiros para uma função ou método, considere este exemplo:

sum(int(x) for x in numbers)

Essa construção é intencionalmente notavelmente semelhante às compreensões de lista mencionadas por adamk. Sem os colchetes, isso é chamado de expressão geradora e é uma maneira muito eficiente em termos de memória de passar uma lista de argumentos para um método. Uma boa discussão está disponível aqui: Expressões do Gerador vs. Compreensão da Lista

Tim McNamara
fonte
4

Outra maneira de fazê-lo no Python 3:

numbers = [*map(int, numbers)]

zhukovgreen
fonte
1
Você pode explicar isso? Não estou familiarizado com essa sintaxe. Obrigado!
abalter
1
Estou usando a lista de argumentos de descompactação ( docs.python.org/3/tutorial/… )
zhukovgreen
Aha, uma coisa de python 3. Parece estranho ter []uma lista de argumentos. E eu não sabia que você poderia passar um iterador como uma lista de argumentos. Eu teria pensado em fazer number = list(map(int, numbers)). Mas obrigado pela explicação!
abalter
3

De outra maneira

for i, v in enumerate(numbers): numbers[i] = int(v)
Nick Dandoulakis
fonte
6
OP disse pythônico
SilentGhost
3
Dessa forma, é muito útil se você deseja executar a operação apenas em alguns dos elementos da lista. Esta não é relevante para a questão neste segmento, mas pode haver casos em que é útil
Dikla
1

Pensei em consolidar as respostas e mostrar alguns timeitresultados.

O Python 2 é péssimo nisso, mas mapé um pouco mais rápido que a compreensão.

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

O Python 3 é 4x mais rápido por si só, mas converter o mapobjeto gerador em uma lista ainda é mais rápido que a compreensão, e criar a lista descompactando o mapgerador (obrigado Artem!) É um pouco mais rápido ainda.

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: No Python 3, 4 elementos parecem ser o ponto de cruzamento (3 no Python 2), onde a compreensão é um pouco mais rápida, embora a descompactação do gerador seja ainda mais rápida do que nas listas com mais de 1 elemento.

Jim
fonte