Pergunta

Eu estava tentando encontrar a maneira mais rápida para contar o número de itens em uma lista de correspondência de um filtro específico.Neste caso, encontrar quantos números ímpares existem em uma lista.

Enquanto isso, fiquei surpreso com os resultados da comparação de uma lista de compreensão vs o equivalente do gerador de expressão:

python -m timeit -s "L = xrange(1000000)" "sum([1 for i in L if i & 1])"
10 loops, best of 3: 109 msec per loop

python -m timeit -s "L = xrange(1000000)" "sum(1 for i in L if i & 1)"
10 loops, best of 3: 125 msec per loop

Eu também tentei com L sendo uma lista regular e tamanhos diferentes, mas em todos os casos, a compreensão lista wins.

O que é o genexp fazendo o que faz com que ele seja mais lento comparado com o listcomp que cria uma nova lista com 1 milhão de itens...?

(Btw, a maneira mais rápida que eu encontrei foi: x = 1; len(filter(x.__and__, L)).E sim, eu sei escrever código como o que mata gatinhos, eu estou fazendo isso por diversão)

Foi útil?

Solução

Quando a memória essencialmente ilimitada estiver disponível (o que invariavelmente será o caso em minúsculos parâmetros de referência, embora muitas vezes não esteja em problemas do mundo real!-), as listas tendem a superar os geradores porque podem ser alocados apenas uma vez, em um "grande grupo" ( Sem fragmentação de memória, etc.), enquanto os geradores exigem um esforço extra (internamente) para evitar essa abordagem de "grande grupo", preservando o estado da estrutura da pilha para permitir a retomada de execução.

Se uma abordagem ou abordagem de listagem ou gerador será mais rápida em um programa real Depende da situação exata da memória, incluindo a fragmentação, que é impossível reproduzir com precisão em um "micro-benchmark". Iow, no final, se você realmente se preocupa com o desempenho, deve comparar cuidadosamente (e, separadamente, perfil) seus programas reais, não apenas os micro-benchmarks de "brinquedo", no caso geral.

Outras dicas

Pelo que eu me lembre, um gerador de quadro tem de ser activada para cada resultado, considerando que a compreensão lista usa a ativação do frame.O custo incremental na lista de compressão é o custo adicional de memória -- referências para int no seu caso.A relação pode muito bem reverter se cada item de uma nova instância e utiliza mais memória.

atualização:Após o teste, ele fez o inverso

~% python -m timeit -s "L = xrange(1000000);oint=type('intEx', (int,),{})" "sum([oint(1) for i in L if i & 1])" 
10 loops, best of 3: 414 msec per loop

~% python -m timeit -s "L = xrange(1000000);oint=type('intEx', (int,),{})" "sum(oint(1) for i in L if i & 1)" 
10 loops, best of 3: 392 msec per loop
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top