Estoy jugando con listas por comprensión y encontré este pequeño fragmento en otro sitio:
return ''.join([`num` for num in xrange(loop_count)])
Pasé unos minutos tratando de replicar la función (escribiendo) antes de darme cuenta de que la `num`
broca la estaba rompiendo.
¿Qué hace incluir una declaración en esos caracteres? Por lo que puedo ver, es el equivalente de str (num). Pero cuando lo cronometré:
return ''.join([str(num) for num in xrange(10000000)])
Tarda 4.09s mientras que:
return ''.join([`num` for num in xrange(10000000)])
tarda 2,43 s.
Ambos dan resultados idénticos, pero uno es mucho más lento. ¿Que esta pasando aqui?
EDITAR: Curiosamente ... repr()
da resultados ligeramente más lentos que `num`
. 2.99 vs 2.43s. Usando Python 2.6 (aún no he probado 3.0).
python
list-comprehension
Dominic Bou-Samra
fuente
fuente
Respuestas:
Las comillas invertidas son un alias obsoleto para
repr()
. No los use más, la sintaxis se eliminó en Python 3.0.Usar comillas invertidas parece ser más rápido que usar
repr(num)
onum.__repr__()
en la versión 2.x. Supongo que se debe a que se requiere una búsqueda adicional en el diccionario en el espacio de nombres global (pararepr
) o en el espacio de nombres del objeto (para__repr__
), respectivamente.El uso del
dis
módulo prueba mi suposición:def f1(a): return repr(a) def f2(a): return a.__repr__() def f3(a): return `a`
Desmontaje muestra:
>>> import dis >>> dis.dis(f1) 3 0 LOAD_GLOBAL 0 (repr) 3 LOAD_FAST 0 (a) 6 CALL_FUNCTION 1 9 RETURN_VALUE >>> dis.dis(f2) 6 0 LOAD_FAST 0 (a) 3 LOAD_ATTR 0 (__repr__) 6 CALL_FUNCTION 0 9 RETURN_VALUE >>> dis.dis(f3) 9 0 LOAD_FAST 0 (a) 3 UNARY_CONVERT 4 RETURN_VALUE
f1
implica una búsqueda global derepr
,f2
una búsqueda de atributos__repr__
, mientras que el operador de comillas invertidas se implementa en un código de operación separado. Dado que no hay sobrecarga para la búsqueda de diccionario (LOAD_GLOBAL
/LOAD_ATTR
) ni para las llamadas a funciones (CALL_FUNCTION
), las comillas invertidas son más rápidas.Supongo que la gente de Python decidió que tener una operación separada de bajo nivel para
repr()
no vale la pena, y tenerrepr()
comillas inversas y ambos viola el principiopor lo que la función se eliminó en Python 3.0.
fuente
Las comillas al revés generalmente no son útiles y desaparecieron en Python 3.
Por lo que vale, esto:
''.join(map(repr, xrange(10000000)))
es un poco más rápido que la versión de comillas invertidas para mí. Pero preocuparse por esto probablemente sea una optimización prematura.
fuente
timeit
produce resultados más rápidos para''.join(map(repr, xrange(0, 1000000)))
que para''.join([repr(i) for i in xrange(0, 1000000)])
(incluso peor para''.join( (repr(i) for i in xrange(0, 1000000)) )
). Es un poco decepcionante ;-)map
se implementa en C, usando un ciclo C, que es mucho más rápido que un ciclo Python ejecutado en la máquina virtual.map
me parece perfectamente claro y conciso, y ni siquiera conozco Python.Supongo que eso
num
no define el método__str__()
, por lo questr()
tiene que hacer una segunda búsqueda__repr__
.Las comillas invertidas buscan directamente
__repr__
. Si eso es cierto, entonces usar enrepr()
lugar de las comillas inversas debería darle los mismos resultados.fuente