¿Qué significan los backticks para el intérprete de python: `num`

Estoy jugando con las listas de 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 el bit `num` estaba rompiendo.

¿Qué hace encerrar una statement en esos personajes? Por lo que puedo ver es el equivalente de str (num). Pero cuando lo cronometré:

 return ''.join([str(num) for num in xrange(10000000)]) 

Se tarda 4.09s mientras que:

 return ''.join([`num` for num in xrange(10000000)]) 

toma 2.43s.

Ambos dan resultados idénticos pero uno es mucho más lento. ¿Que esta pasando aqui?

EDIT: Extrañamente … repr() da resultados un poco más lentos que `num` . 2.99s vs 2.43s. Usando Python 2.6 (no he probado 3.0 aún).

Backticks son un alias en desuso para repr() . No los uses más, la syntax se eliminó en Python 3.0.

Utilizar backticks parece ser más rápido que usar repr(num) o num.__repr__() en la versión 2.x. Supongo que se debe a que se requiere una búsqueda de diccionario adicional en el espacio de nombres global (para repr ), o en el espacio de nombres del objeto (para __repr__ ), respectivamente.


El uso del módulo dis prueba mi suposición:

 def f1(a): return repr(a) def f2(a): return a.__repr__() def f3(a): return `a` 

Desassembly de espectáculos:

 >>> 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 para repr , f2 una búsqueda de atributo para __repr__ , mientras que el operador de __repr__ se implementa en un código de operación independiente. Como no hay gastos generales para la búsqueda de diccionarios ( LOAD_GLOBAL / LOAD_ATTR ) ni para las llamadas de función ( CALL_FUNCTION ), los backticks son más rápidos.

Supongo que la gente de Python decidió que tener una operación separada de bajo nivel para repr() no vale la pena, y tener repr() y backticks viola el principio

“Debería haber una, y preferiblemente solo una, obvia forma de hacerlo”

por lo que la característica se eliminó en Python 3.0.

Las citas de comillas invertidas generalmente no son útiles y desaparecen en Python 3.

Por lo que vale, esto:

 ''.join(map(repr, xrange(10000000))) 

es ligeramente más rápido que la versión de comillas invertidas para mí. Pero preocuparse por esto es probablemente una optimización prematura.

Mi conjetura es que num no define el método __str__() , por lo que str() debe hacer una segunda búsqueda de __repr__ .

Los backticks buscan directamente __repr__ . Si eso es cierto, entonces usar repr() lugar de las comillas invertidas debería darte los mismos resultados.