rendimiento de str en python

Al perfilar un fragmento de código de Python ( python 2.6 hasta 3.2 ), descubrí que el método str para convertir un objeto (en mi caso un entero) en una cadena es casi un orden de magnitud más lento que usar el formato de cadena.

Aquí está el punto de referencia

 >>> from timeit import Timer >>> Timer('str(100000)').timeit() 0.3145311339386332 >>> Timer('"%s"%100000').timeit() 0.03803517023435887 

¿Alguien sabe por qué este es el caso? ¿Me estoy perdiendo de algo?

'%s' % 100000 es evaluado por el comstackdor y es equivalente a una constante en tiempo de ejecución.

 >>> import dis >>> dis.dis(lambda: str(100000)) 8 0 LOAD_GLOBAL 0 (str) 3 LOAD_CONST 1 (100000) 6 CALL_FUNCTION 1 9 RETURN_VALUE >>> dis.dis(lambda: '%s' % 100000) 9 0 LOAD_CONST 3 ('100000') 3 RETURN_VALUE 

% con una expresión en tiempo de ejecución no es (significativamente) más rápido que str :

 >>> Timer('str(x)', 'x=100').timeit() 0.25641703605651855 >>> Timer('"%s" % x', 'x=100').timeit() 0.2169809341430664 

Tenga en cuenta que str es aún un poco más lento, como dijo @DietrichEpp, esto se debe a que str implica operaciones de búsqueda y llamada de función, mientras que % comstack en un solo bytecode inmediato:

 >>> dis.dis(lambda x: str(x)) 9 0 LOAD_GLOBAL 0 (str) 3 LOAD_FAST 0 (x) 6 CALL_FUNCTION 1 9 RETURN_VALUE >>> dis.dis(lambda x: '%s' % x) 10 0 LOAD_CONST 1 ('%s') 3 LOAD_FAST 0 (x) 6 BINARY_MODULO 7 RETURN_VALUE 

Por supuesto, lo anterior es cierto para el sistema que probé (CPython 2.7); Otras implementaciones pueden diferir.

Una razón que viene a la mente es el hecho de que str(100000) implica una búsqueda global, pero "%s"%100000 no lo hace. El str global debe ser buscado en el ámbito global. Esto no tiene en cuenta la diferencia completa:

 >>> Timer('str(100000)').timeit() 0.2941889762878418 >>> Timer('x(100000)', 'x=str').timeit() 0.24904918670654297 

Como lo señaló thg435 ,

 >>> Timer('"%s"%100000',).timeit() 0.034214019775390625 >>> Timer('"%s"%x','x=100000').timeit() 0.2940788269042969