Según la respuesta de John Fouhy, no optimices a menos que tengas que hacerlo, pero si estás aquí y haces esta pregunta, puede ser precisamente porque tienes que hacerlo . En mi caso, necesitaba ensamblar algunas URL de variables de cadena ... rápido. Noté que nadie (hasta ahora) parece estar considerando el método de formato de cadena, por lo que pensé en probarlo y, sobre todo por un leve interés, pensé en tirar el operador de interpolación de cadena allí para una buena medición. Para ser honesto, no pensé que ninguno de estos se apilara a una operación directa '+' o un '' .join (). ¿Pero adivina que? En mi sistema Python 2.7.5, el operador de interpolación de cadenas los gobierna a todos y string.format () es el de peor desempeño:
# concatenate_test.py
from __future__ import print_function
import timeit
domain = 'some_really_long_example.com'
lang = 'en'
path = 'some/really/long/path/'
iterations = 1000000
def meth_plus():
'''Using + operator'''
return 'http://' + domain + '/' + lang + '/' + path
def meth_join():
'''Using ''.join()'''
return ''.join(['http://', domain, '/', lang, '/', path])
def meth_form():
'''Using string.format'''
return 'http://{0}/{1}/{2}'.format(domain, lang, path)
def meth_intp():
'''Using string interpolation'''
return 'http://%s/%s/%s' % (domain, lang, path)
plus = timeit.Timer(stmt="meth_plus()", setup="from __main__ import meth_plus")
join = timeit.Timer(stmt="meth_join()", setup="from __main__ import meth_join")
form = timeit.Timer(stmt="meth_form()", setup="from __main__ import meth_form")
intp = timeit.Timer(stmt="meth_intp()", setup="from __main__ import meth_intp")
plus.val = plus.timeit(iterations)
join.val = join.timeit(iterations)
form.val = form.timeit(iterations)
intp.val = intp.timeit(iterations)
min_val = min([plus.val, join.val, form.val, intp.val])
print('plus %0.12f (%0.2f%% as fast)' % (plus.val, (100 * min_val / plus.val), ))
print('join %0.12f (%0.2f%% as fast)' % (join.val, (100 * min_val / join.val), ))
print('form %0.12f (%0.2f%% as fast)' % (form.val, (100 * min_val / form.val), ))
print('intp %0.12f (%0.2f%% as fast)' % (intp.val, (100 * min_val / intp.val), ))
Los resultados:
# python2.7 concatenate_test.py
plus 0.360787868500 (90.81% as fast)
join 0.452811956406 (72.36% as fast)
form 0.502608060837 (65.19% as fast)
intp 0.327636957169 (100.00% as fast)
Si uso un dominio más corto y una ruta más corta, la interpolación sigue ganando. Sin embargo, la diferencia es más pronunciada con cadenas más largas.
Ahora que tenía un buen script de prueba, también probé en Python 2.6, 3.3 y 3.4, aquí están los resultados. ¡En Python 2.6, el operador plus es el más rápido! En Python 3, unirse gana. Nota: estas pruebas son muy repetibles en mi sistema. Entonces, 'plus' siempre es más rápido en 2.6, 'intp' siempre es más rápido en 2.7 y 'join' siempre es más rápido en Python 3.x.
# python2.6 concatenate_test.py
plus 0.338213920593 (100.00% as fast)
join 0.427221059799 (79.17% as fast)
form 0.515371084213 (65.63% as fast)
intp 0.378169059753 (89.43% as fast)
# python3.3 concatenate_test.py
plus 0.409130576998 (89.20% as fast)
join 0.364938726001 (100.00% as fast)
form 0.621366866995 (58.73% as fast)
intp 0.419064424001 (87.08% as fast)
# python3.4 concatenate_test.py
plus 0.481188605998 (85.14% as fast)
join 0.409673971997 (100.00% as fast)
form 0.652010936996 (62.83% as fast)
intp 0.460400978001 (88.98% as fast)
# python3.5 concatenate_test.py
plus 0.417167026084 (93.47% as fast)
join 0.389929617057 (100.00% as fast)
form 0.595661019906 (65.46% as fast)
intp 0.404455224983 (96.41% as fast)
Lección aprendida:
- A veces, mis suposiciones están completamente equivocadas.
- Prueba contra el sistema env. estarás corriendo en producción.
- ¡La interpolación de cuerdas aún no está muerta!
tl; dr:
- Si usa 2.6, use el operador +.
- si está utilizando 2.7, use el operador '%'.
- si está utilizando 3.x use '' .join ().