Ответ 1
- Да, форматирование строки
%
быстрее, чем метод.format
- наиболее вероятно (это может иметь гораздо лучшее объяснение) из-за того, что
%
является синтаксической нотацией (отсюда и быстрое выполнение), тогда как.format
включает как минимум один дополнительный вызов метода - потому что доступ к значению атрибута также включает дополнительный вызов метода, а именно.
__getattr__
Я провел немного лучший анализ (на Python 3.6.0), используя timeit
различных методов форматирования, результаты которых выглядят следующим образом (красиво напечатано с BeautifulTable) -
+-----------------+-------+-------+-------+-------+-------+--------+ | Type \ num_vars | 1 | 2 | 5 | 10 | 50 | 250 | +-----------------+-------+-------+-------+-------+-------+--------+ | f_str_str | 0.306 | 0.064 | 0.106 | 0.183 | 0.737 | 3.422 | +-----------------+-------+-------+-------+-------+-------+--------+ | f_str_int | 0.295 | 0.174 | 0.385 | 0.686 | 3.378 | 16.399 | +-----------------+-------+-------+-------+-------+-------+--------+ | concat_str | 0.012 | 0.053 | 0.156 | 0.31 | 1.707 | 16.762 | +-----------------+-------+-------+-------+-------+-------+--------+ | pct_s_str | 0.056 | 0.178 | 0.275 | 0.469 | 1.872 | 9.191 | +-----------------+-------+-------+-------+-------+-------+--------+ | pct_s_int | 0.128 | 0.208 | 0.343 | 0.605 | 2.483 | 13.24 | +-----------------+-------+-------+-------+-------+-------+--------+ | dot_format_str | 0.418 | 0.217 | 0.343 | 0.58 | 2.241 | 11.163 | +-----------------+-------+-------+-------+-------+-------+--------+ | dot_format_int | 0.416 | 0.277 | 0.476 | 0.811 | 3.378 | 17.829 | +-----------------+-------+-------+-------+-------+-------+--------+ | dot_format2_str | 0.433 | 0.242 | 0.416 | 0.675 | 3.152 | 16.783 | +-----------------+-------+-------+-------+-------+-------+--------+ | dot_format2_int | 0.428 | 0.298 | 0.541 | 0.933 | 4.444 | 24.767 | +-----------------+-------+-------+-------+-------+-------+--------+
_str
& _int
представляют операцию, которая была выполнена для соответствующих типов значений.
Пожалуйста, обратите внимание, что результат concat_str
для одной переменной по сути является просто самой строкой, поэтому его не следует рассматривать.
Моя установка для достижения результатов -
from timeit import timeit
from beautifultable import BeautifulTable # pip install beautifultable
times = {}
for num_vars in (1, 2, 5, 10, 50, 250):
f_str = "f'{" + '}{'.join([f'x{i}' for i in range(num_vars)]) + "}'"
# "f'{x0}{x1}"
concat = '+'.join([f'x{i}' for i in range(num_vars)])
# 'x0+x1'
pct_s = '"' + '%s'*num_vars + '" % (' + ','.join([f'x{i}' for i in range(num_vars)]) + ')'
# '"%s%s" % (x0,x1)'
dot_format = '"' + '{}'*num_vars + '".format(' + ','.join([f'x{i}' for i in range(num_vars)]) + ')'
# '"{}{}".format(x0,x1)'
dot_format2 = '"{' + '}{'.join([f'{i}' for i in range(num_vars)]) + '}".format(' + ','.join([f'x{i}' for i in range(num_vars)]) + ')'
# '"{0}{1}".format(x0,x1)'
vars = ','.join([f'x{i}' for i in range(num_vars)])
vals_str = tuple(map(str, range(num_vars)))
setup_str = f'{vars} = {vals_str}'
# "x0,x1 = ('0', '1')"
vals_int = tuple(range(num_vars))
setup_int = f'{vars} = {vals_int}'
# 'x0,x1 = (0, 1)'
times[num_vars] = {
'f_str_str': timeit(f_str, setup_str),
'f_str_int': timeit(f_str, setup_int),
'concat_str': timeit(concat, setup_str),
# 'concat_int': timeit(concat, setup_int), # this will be summation, not concat
'pct_s_str': timeit(pct_s, setup_str),
'pct_s_int': timeit(pct_s, setup_int),
'dot_format_str': timeit(dot_format, setup_str),
'dot_format_int': timeit(dot_format, setup_int),
'dot_format2_str': timeit(dot_format2, setup_str),
'dot_format2_int': timeit(dot_format2, setup_int),
}
table = BeautifulTable()
table.column_headers = ['Type \ num_vars'] + list(map(str, times.keys()))
# Order is preserved, so I didn't worry much
for key in ('f_str_str', 'f_str_int', 'concat_str', 'pct_s_str', 'pct_s_int', 'dot_format_str', 'dot_format_int', 'dot_format2_str', 'dot_format2_int'):
table.append_row([key] + [times[num_vars][key] for num_vars in (1, 2, 5, 10, 50, 250)])
print(table)
Я не мог выйти за пределы num_vars=250
из-за ограничения максимального количества аргументов (255) с timeit
.
tl; dr - производительность форматирования строки Python: f-strings
быстрее и элегантнее, но иногда (из-за некоторых ограничений реализации и только из Py3. 6+) вам, возможно, придется использовать другие параметры форматирования по мере необходимости.