Форматирование строк и конкатенации
Я вижу много людей, использующих такие строки формата:
root = "sample"
output = "output"
path = "{}/{}".format(root, output)
Вместо просто конкатенации таких строк:
path = root + '/' + output
Имеют ли строки формата лучшую производительность или это просто для внешнего вида?
Ответы
Ответ 1
Это только для внешности. Вы можете сразу увидеть, что это за формат. Многим из нас нравится читаемость лучше, чем микрооптимизация.
Давайте посмотрим, что говорит IPython %timeit
:
Python 3.7.2 (default, Jan 3 2019, 02:55:40)
IPython 5.8.0
Intel(R) Core(TM) i5-4590T CPU @ 2.00GHz
In [1]: %timeit root = "sample"; output = "output"; path = "{}/{}".format(root, output)
The slowest run took 12.44 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 5: 223 ns per loop
In [2]: %timeit root = "sample"; output = "output"; path = root + '/' + output
The slowest run took 13.82 times longer than the fastest. This could mean that an intermediate result is being cached.
10000000 loops, best of 5: 101 ns per loop
In [3]: %timeit root = "sample"; output = "output"; path = "%s/%s" % (root, output)
The slowest run took 27.97 times longer than the fastest. This could mean that an intermediate result is being cached.
10000000 loops, best of 5: 155 ns per loop
In [4]: %timeit root = "sample"; output = "output"; path = f"{root}/{output}"
The slowest run took 19.52 times longer than the fastest. This could mean that an intermediate result is being cached.
10000000 loops, best of 5: 77.8 ns per loop
Ответ 2
Как и в большинстве случаев, будет разница в производительности, но спросите себя: "Действительно ли это имеет значение, если это быстрее?". Метод root + '/' output
можно быстро и легко распечатать. Но это может усложниться, чтобы быстро прочитать, когда у вас есть несколько переменных для печати
foo = "X = " + myX + " | Y = " + someY + " Z = " + Z.toString()
против
foo = "X = {} | Y= {} | Z = {}".format(myX, someY, Z.toString())
Что легче понять, что происходит? Если вам действительно не нужно выполнять производительность, выберите способ, который будет проще для людей читать и понимать
Ответ 3
Формат строки не содержит данных при привязке данных. В то время как в конкатенации мы должны набирать букву или преобразовывать данные соответственно.
Например:
a = 10
b = "foo"
c = str(a) + " " + b
print c
> 10 foo
Это можно сделать с помощью форматирования строк:
a = 10
b = "foo"
c = "{} {}".format(a, b)
print c
> 10 foo
Таким образом, что с-in placeholders {} {}
, мы предполагаем, что две вещи должны прийти далее, то есть в этом случае a
и b
.
Ответ 4
Это не только для "взглядов", либо для мощных преобразований лексического типа; это также необходимо для интернационализации.
Вы можете поменять строку формата в зависимости от выбранного языка.
С длинной строкой конкатенаций строк, испеченных в исходный код, это становится практически невозможным для правильной работы.
Ответ 5
Я согласен с тем, что форматирование в основном используется для удобочитаемости, но с момента выпуска f-строк в 3.6 таблицы превратились в терминах производительности. Также я считаю, что f-строки являются более читабельными/поддерживаемыми, поскольку 1) их можно читать влево-вправо, как и в большинстве обычных текстов, и 2) недостатки конкатенации, связанные с интервалом, исключаются, поскольку переменные являются встроенными.
Запуск этого кода:
from timeit import timeit
runs = 1000000
def print_results(time, start_string):
print(f'{start_string}\n'
f'Total: {time:.4f}s\n'
f'Avg: {(time/runs)*1000000000:.4f}ns\n')
t1 = timeit('"%s, %s" % (greeting, loc)',
setup='greeting="hello";loc="world"',
number=runs)
t2 = timeit('f"{greeting}, {loc}"',
setup='greeting="hello";loc="world"',
number=runs)
t3 = timeit('greeting + ", " + loc',
setup='greeting="hello";loc="world"',
number=runs)
t4 = timeit('"{}, {}".format(greeting, loc)',
setup='greeting="hello";loc="world"',
number=runs)
print_results(t1, '% replacement')
print_results(t2, 'f strings')
print_results(t3, 'concatenation')
print_results(t4, '.format method')
дает этот результат на моей машине:
% replacement
Total: 0.3044s
Avg: 304.3638ns
f strings
Total: 0.0991s
Avg: 99.0777ns
concatenation
Total: 0.1252s
Avg: 125.2442ns
.format method
Total: 0.3483s
Avg: 348.2690ns
Подобный ответ на другой вопрос дается на этом ответе.
Ответ 6
Начиная с Python 3.6 вы можете выполнять интерполяцию литеральных строк, предварительно введя f
в строку:
root = "sample"
output = "output"
path = f"{root}/{output}"
Ответ 7
Это для просмотра и сохранения кода. Редактировать свой код очень удобно, если вы использовали формат. Также, когда вы используете +, вы можете пропустить такие детали, как пробелы. Используйте формат для вашего и возможного сопровождения.