Estou brincando com as compreensões de listas e encontrei este pequeno trecho em outro site:
return ''.join([`num` for num in xrange(loop_count)])
Passei alguns minutos tentando replicar a função (digitando) antes de perceber que o `num`
bit a estava quebrando.
O que incluir uma declaração nesses caracteres? Pelo que posso ver, é o equivalente a str (num). Mas quando eu cronometrei:
return ''.join([str(num) for num in xrange(10000000)])
Leva 4,09s, enquanto:
return ''.join([`num` for num in xrange(10000000)])
leva 2,43s.
Ambos fornecem resultados idênticos, mas um é muito mais lento. O que está acontecendo aqui?
EDIT: Estranhamente ... repr()
dá resultados ligeiramente mais lentos do que `num`
. 2,99s vs 2,43s. Usando Python 2.6 (não tentei 3.0 ainda).
python
list-comprehension
Dominic Bou-Samra
fonte
fonte
Respostas:
Backticks são um alias obsoleto para
repr()
. Não os use mais, a sintaxe foi removida no Python 3.0.Usar crases parece ser mais rápido do que usar
repr(num)
ounum.__repr__()
na versão 2.x. Acho que é porque a pesquisa de dicionário adicional é necessária no namespace global (forrepr
) ou no namespace do objeto (for__repr__
), respectivamente.Usar o
dis
módulo prova minha suposição:Desmontando programas:
f1
envolve uma pesquisa global pararepr
,f2
uma pesquisa de atributo para__repr__
, enquanto o operador crase é implementado em um opcode separado. Uma vez que não há sobrecarga para pesquisa de dicionário (LOAD_GLOBAL
/LOAD_ATTR
) nem para chamadas de função (CALL_FUNCTION
), crases são mais rápidos.Acho que o pessoal do Python decidiu que
repr()
não vale a pena ter uma operação de baixo nível separada para , e ter ambos osrepr()
crases viola o princípioportanto, o recurso foi removido no Python 3.0.
fonte
As citações de backtick geralmente não são úteis e desapareceram no Python 3.
Por que vale a pena, isto:
é ligeiramente mais rápido do que a versão backtick para mim. Mas se preocupar com isso é provavelmente uma otimização prematura.
fonte
timeit
produz resultados mais rápidos para do''.join(map(repr, xrange(0, 1000000)))
que para''.join([repr(i) for i in xrange(0, 1000000)])
(ainda pior para''.join( (repr(i) for i in xrange(0, 1000000)) )
). É um pouco decepcionante ;-)map
é implementado em C, usando um loop C, que é muito mais rápido do que um loop Python executado na máquina virtual.map
parece perfeitamente claro e conciso para mim, e eu nem mesmo conheço Python.Meu palpite é que
num
isso não define o método__str__()
, entãostr()
é necessário fazer uma segunda pesquisa para__repr__
.Os acúmulos procuram diretamente
__repr__
. Se isso for verdade, usar emrepr()
vez dos crases deve dar os mesmos resultados.fonte