Zgodnie z odpowiedzią Johna Fouhy'ego, nie optymalizuj, chyba że musisz, ale jeśli jesteś tutaj i zadajesz to pytanie, może to być właśnie dlatego, że musisz . W moim przypadku potrzebowałem złożyć kilka adresów URL ze zmiennych łańcuchowych ... szybko. Zauważyłem, że nikt (jak dotąd) nie rozważał metody formatu ciągów, więc pomyślałem, że spróbuję tego i, głównie ze względu na niewielkie zainteresowanie, pomyślałem, że wrzucę tam operator interpolacji ciągów dla dobrego pomiaru. Szczerze mówiąc, nie sądziłem, że którykolwiek z nich będzie się wiązał z bezpośrednią operacją „+” lub „.join ()”. Ale zgadnij co? W moim systemie Python 2.7.5 operator interpolacji ciągów rządzi wszystkimi, a string.format () jest najgorszy:
# 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), ))
Wyniki:
# 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)
Jeśli użyję krótszej domeny i krótszej ścieżki, nadal wygrywa interpolacja. Różnica jest jednak wyraźniejsza w przypadku dłuższych sznurków.
Teraz, gdy miałem ładny skrypt testowy, testowałem również pod Pythonem 2.6, 3.3 i 3.4, oto wyniki. W Pythonie 2.6 operator plus jest najszybszy! W Pythonie 3 dołączanie wygrywa. Uwaga: te testy są bardzo powtarzalne w moim systemie. Tak więc „plus” jest zawsze szybszy w 2.6, „intp” jest zawsze szybszy w 2.7, a „join” jest zawsze szybszy w Pythonie 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)
Wyciągnięta lekcja:
- Czasami moje założenia są całkowicie błędne.
- Przetestuj pod kątem środowiska systemowego. będziesz pracować w produkcji.
- Interpolacja ciągów jeszcze nie umarła!
tl; dr:
- Jeśli używasz wersji 2.6, użyj operatora +.
- jeśli używasz wersji 2.7, użyj operatora „%”.
- jeśli używasz 3.x użyj '' .join ().