Selon la réponse de John Fouhy, n'optimisez pas sauf si vous devez le faire, mais si vous êtes ici et que vous posez cette question, c'est peut-être précisément parce que vous devez le faire . Dans mon cas, j'avais besoin d'assembler des URL à partir de variables de chaîne ... rapidement. Je n'ai remarqué que personne (jusqu'à présent) ne semble envisager la méthode du format de chaîne, alors j'ai pensé essayer cela et, surtout pour un intérêt léger, j'ai pensé que je jetterais l'opérateur d'interpolation de chaîne là-dedans pour un bon mesureur. Pour être honnête, je ne pensais pas que l'un ou l'autre de ces éléments s'empilerait jusqu'à une opération directe «+» ou un «.join ()». Mais devinez quoi? Sur mon système Python 2.7.5, l'opérateur d'interpolation de chaîne les règle tous et string.format () est le moins performant:
# 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), ))
Les resultats:
# 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 j'utilise un domaine plus court et un chemin plus court, l'interpolation l'emporte toujours. La différence est cependant plus prononcée avec des cordes plus longues.
Maintenant que j'avais un joli script de test, j'ai également testé sous Python 2.6, 3.3 et 3.4, voici les résultats. En Python 2.6, l'opérateur plus est le plus rapide! Sur Python 3, rejoindre l'emporte. Remarque: ces tests sont très répétables sur mon système. Ainsi, «plus» est toujours plus rapide sur 2.6, «intp» est toujours plus rapide sur 2.7 et «join» est toujours plus rapide sur 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)
Leçon apprise:
- Parfois, mes hypothèses sont complètement fausses.
- Test contre le système env. vous serez en production.
- L'interpolation de chaîne n'est pas encore morte!
tl; dr:
- Si vous utilisez 2.6, utilisez l'opérateur +.
- si vous utilisez 2.7, utilisez l'opérateur '%'.
- si vous utilisez 3.x utilisez '' .join ().