Форматирование строк против конкатенации
Заголовок: Зачем использовать форматированные строки вместо конкатенации?
Текст проблемы:
Я замечаю, что многие программисты используют форматированные строки следующим образом:
root = "sample"
output = "output"
path = "{}/{}".format(root, output)
Вместо того чтобы просто конкатенировать строки таким образом:
path = root + '/' + output
Меня интересует, есть ли у форматированных строк какое-то преимущество в производительности, или это делается только для повышения читабельности кода?
5 ответ(ов)
Это сделано исключительно для удобства восприятия. На первый взгляд сразу видно, в каком формате представлена строка. Многие из нас предпочитают читаемость кода микропроизводительности.
Посмотрим, что говорит %timeit
в IPython:
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)
Самая медленная итерация заняла 12.44 раз дольше, чем самая быстрая. Это может означать, что промежуточный результат кэшируется.
1000000 циклов, лучшее из 5: 223 нс за цикл
In [2]: %timeit root = "sample"; output = "output"; path = root + '/' + output
Самая медленная итерация заняла 13.82 раз дольше, чем самая быстрая. Это может означать, что промежуточный результат кэшируется.
10000000 циклов, лучшее из 5: 101 нс за цикл
In [3]: %timeit root = "sample"; output = "output"; path = "%s/%s" % (root, output)
Самая медленная итерация заняла 27.97 раз дольше, чем самая быстрая. Это может означать, что промежуточный результат кэшируется.
10000000 циклов, лучшее из 5: 155 нс за цикл
In [4]: %timeit root = "sample"; output = "output"; path = f"{root}/{output}"
Самая медленная итерация заняла 19.52 раз дольше, чем самая быстрая. Это может означать, что промежуточный результат кэшируется.
10000000 циклов, лучшее из 5: 77.8 нс за цикл
Как видно из результатов, использование f-строк (в четвертом примере) показывает наилучшее время выполнения, но, как я уже говорил, иногда более важно писать читаемый код, чем стремиться к максимальной производительности в каждом конкретном случае.
Как и во многих других вопросах, между этими подходами действительно есть разница в производительности, но стоит задать себе вопрос: «Насколько важна эта разница в несколько наносекунд?» Метод root + '/' output
быстро и легко писать, однако он может стать трудночитаемым, когда нужно вывести несколько переменных.
Например, такой вариант:
foo = "X = " + myX + " | Y = " + someY + " | Z = " + Z.toString()
входит в резкое противоречие с этим:
foo = "X = {} | Y = {} | Z = {}".format(myX, someY, Z.toString())
Какой из вариантов легче понять? Если не требуется совсем выжимать производительность, лучше выбрать способ, который будет проще читать и понимать другим людям.
Это не просто для «красоты» или мощных лексических преобразований типов; это также необходимо для интернационализации.
Вы можете менять формат строк в зависимости от выбранного языка.
С длинной линией конкатенаций строк, встроенной в исходный код, это становится фактически невозможным сделать правильно.
Форматирование строк в Python позволяет работать с данными разных типов без необходимости явного преобразования, в отличие от конкатенации, где требуется приведение типов.
Например, если у вас есть:
a = 10
b = "foo"
c = str(a) + " " + b
print(c)
На выходе вы получите:
10 foo
Однако это можно сделать проще и чище с помощью форматирования строк. Вместо того чтобы явно приводить a
к строке, вы можете использовать метод format()
:
a = 10
b = "foo"
c = "{} {}".format(a, b)
print(c)
В этом случае на выходе вы также получите:
10 foo
Здесь внутри фигурных скобок {}
мы подразумеваем, что на их месте появятся значения переменных a
и b
. Это делает код более читаемым и удобным для работы с различными типами данных.
Это делается для улучшения внешнего вида и удобства сопровождения кода. На самом деле, редактировать ваш код становится намного проще, если вы используете форматирование. Когда вы используете оператор + для соединения строк, вы можете упустить такие детали, как пробелы. Используйте форматирование в своих интересах и в интересах возможных сопровождателей вашего кода.
Как экранировать фигурные скобки ({}) в строке при использовании .format?
Как заполнить строку в Python пробелами?
Использование locals() и метода format() для строк: есть ли подводные камни?
Ошибка форматирования текста: недопустимое выравнивание '=' в спецификаторе формата строки
Как изменить порядок столбцов в DataFrame?