Часто при написании кода на Python нам требуется представить объект определенным образом или включить значения каких-либо выражений внутрь строки. Для этого мы можем использовать форматирование строк. При этом в Python существуют сразу три способа форматирования строк:
оператор
%строковый метод
format()f-строки
Причиной такого разнообразия является развитие языка Python и постоянное совершенствование его инструментария. Один способ форматирования устаревает, ему на смену приходит новый, более удобный и практичный. Однако устаревшие способы форматирования строк было решено оставить в Python, в первую очередь для обеспечения обратной совместимости со старыми версиями языка. Каждый из способов форматирования может использоваться и по сей день.
В этой статье мы рассмотрим эволюцию способов форматирования строк и разберем их преимущества и недостатки.
Оператор %
Оператор % является первым способом форматирования строк, который появился в Python. Он был заимствован из языка C, на котором написан основной интерпретатор Python, поэтому данный способ форматирования строк также называют форматированием в стиле С.
Для форматирования с помощью оператора % необходимо слева от оператора указать строку с заполнителем %s, а справа — подставляемое в нее значение.
Приведенный ниже код:
print('My name is %s' % 'James')
выводит:
My name is James
Символ s в заполнителе обозначает преобразование подставляемого значения в формат строки. Мы можем использовать и другие форматы, наиболее важные из которых приведены в таблице ниже:
формат |
значение |
|
целое число |
|
число с плавающей точкой |
|
число в восьмеричной системе счисления |
|
число в шестнадцатеричной системе счисления |
|
число в экспоненциальном формате |
|
формальное строковое представление объекта (аналогично функции |
Например, вместо символа s можно указать в заполнителе символ f, который указывает на преобразование подставляемого значения в формат числа с плавающей точкой.
Если необходимо подставить в строку несколько значений, то их нужно перечислить в кортеже. При этом количество заполнителей должно соответствовать количеству подставляемых значений. В противном случае будет возбуждено исключение TypeError. В процессе форматирования кортеж распаковывается и его элементы помещаются на место заполнителей поочередно слева направо.
Приведенный ниже код:
name = 'James'
surname = 'Bond'
result = 'My name is %s, %s %s' % (surname, name, surname)
print(result)
выводит:
My name is Bond, James Bond
Также допускается подстановка значений из словаря. Для этого в каждом заполнителе между символом % и форматом представления необходимо в круглых скобках указать ключ словаря, значение которого требуется поместить в строку вместо заполнителя. При этом можно использовать один и тот же ключ в нескольких заполнителях.
Приведенный ниже код:
person = {'name': 'James', 'surname': 'Bond'}
result = 'My name is %(surname)s, %(name)s %(surname)s' % person
print(result)
выводит:
My name is Bond, James Bond
Основным недостатком %-форматирования является сложность в использовании и избыточность кода в случаях, когда требуется подставить в строку большое количество значений. Кроме того, %-форматирование имеет ряд особенностей, которые часто приводят к ошибкам. Например, стоит соблюдать осторожность при подстановке кортежа в строку, которая содержит один заполнитель.
Приведенный ниже код:
person = ('James', 'Bond')
result = 'person: %s' % person
print(result)
приводит к возбуждению исключения:
TypeError: not all arguments converted during string formatting
Вместо ожидаемого вывода person: ('James', 'Bond') мы получаем ошибку. Это происходит потому, что за кулисами Python распаковывает кортеж и пытается поместить в строку все его элементы, однако заполнитель в строке всего один. Для решения данной проблемы можно явно преобразовать кортеж в строку.
Приведенный ниже код:
person = ('James', 'Bond')
result = 'person: %s' % str(person)
print(result)
выводит:
person: ('James', 'Bond')
Кстати, форматирование строки, в результате которого заполнители заменяются значениями, называется интерполяцией. ✍️
Начиная с Python 3.0 форматирование с помощью оператора % считается устаревшим способом форматирования строк. Ему на смену пришел более удобный и гибкий способ — строковый метод format().
Строковый метод format()
Строковый метод format() возвращает копию строки, в которой каждый заполнитель {} заменяется строковым представлением соответствующего переданного аргумента.
Аргументы метода:
*args— позиционные аргументы**kwargs— именованные аргументы
При подстановке позиционных аргументов их значения помещаются на место заполнителей поочередно слева направо.
Приведенный ниже код:
name = 'James'
surname = 'Bond'
result = 'My name is {}, {} {}'.format(surname, name, surname)
print(result)
выводит:
My name is Bond, James Bond
Если количество заполнителей больше, чем количество переданных позиционных аргументов, будет возбуждено исключение IndexError, если меньше — значения аргументов, которым не хватило заполнителей, будут отброшены.
Приведенный ниже код:
name = 'James'
surname = 'Bond'
result = 'My name is {}'.format(name, surname)
print(result)
выводит:
My name is James
Для наглядности и гибкости форматирования можно использовать порядковый номер аргумента в заполнителе (нумерация начинается с нуля). Первый из переданных в метод аргументов занимает место заполнителя {0}, второй — {1}, и так далее. При этом мы можем использовать одно и то же число в нескольких заполнителях.
Приведенный ниже код:
name = 'James'
surname = 'Bond'
result = 'My name is {1}, {0} {1}'.format(name, surname)
print(result)
выводит:
My name is Bond, James Bond
При подстановке именованных аргументов в заполнителе необходимо указать имя аргумента, значение которого требуется поместить в строку вместо заполнителя. При этом мы можем использовать одно и то же имя в нескольких заполнителях. Если имя аргумента не указано в заполнителе, возбуждается исключение KeyError.
Приведенный ниже код:
result = 'My name is {surname}, {name} {surname}'.format(name='James', surname='Bond')
print(result)
выводит:
My name is Bond, James Bond
Также допускается одновременная подстановка в строку позиционных и именованных аргументов.
Приведенный ниже код:
name = 'James'
result = 'My name is {surname}, {0} {surname}'.format(name, surname='Bond')
print(result)
выводит:
My name is Bond, James Bond
Основным недостатком форматирования строк с помощью метода format() является избыточность кода в случаях, когда требуется подставить в строку большое количество значений.
f-строки
В Python 3.6 появился новый способ форматирования строк — f-строки (formatted string literals, f-strings). F-строка представляет собой строку с префиксом 'f' или 'F', которая может содержать заполнители {}. В каждый заполнитель помещаются переменные или выражения, значения которых объединяются со строковой частью f-строки.
Приведенный ниже код:
name = 'James'
surname = 'Bond'
result = f'My name is {surname}, {name.upper()} {surname.upper()}'
print(result)
выводит:
My name is Bond, JAMES BOND
Если в заполнитель f-строки требуется подставить строковый литерал напрямую, кавычки f-строки и подставляемого строкового литерала должны быть различны (это ограничение действует до версии Python 3.12).
Приведенный ниже код:
print(f'My name is {"Bond"}, {"James"} {"Bond"}')
выводит:
My name is Bond, James Bond
Фигурные скобки {} в f-строках являются специальными символами для обозначения заполнителей. Для вывода в итоговой строке самих фигурных скобок их необходимо экранировать. Для этого используется экранирование двойными фигурными скобками {{}}.
Приведенный ниже код:
num = 10
print(f'{{num}}')
выводит:
{num}
Обратите внимание, что выражение внутри {{}} не вычисляется. Если нужно вычислить значение выражения, необходимо использовать тройные фигурные скобки {{{}}}.
Приведенный ниже код:
num = 10
print(f'{{{num}}}')
выводит:
{10}
Для вывода двух фигурных скобок {{}} в f-строке необходимо использовать 4 фигурные скобки {{{{}}}} и еще {} для вычисления выражения. В общем виде количество экранирующих фигурных скобок вычисляется согласно правилу: четное количество {} + {}, если нужно вычислить выражение.
Приведенный ниже код:
num = 10
print(f'{{{{num}}}}')
print(f'{{{{{num}}}}}')
выводит:
{{num}}
{{10}}
Если в строковой части f-строки содержатся управляющие последовательности, то для вывода в явном виде их необходимо экранировать с помощью символа обратной косой черты \.
Приведенный ниже код:
print(f'\\a\\b\\f\\n\\r\\t\\v')
выводит:
\a\b\f\n\r\t\v
Также возможно использование сочетания f-строк и сырых (raw) строк.
Приведенный ниже код:
print(fr'\a\b\f\n\r\t\v')
выводит:
\a\b\f\n\r\t\v
F-строки имеют ряд преимуществ по сравнению с другими способами форматирования строк: они работают быстрее, имеют простой и гибкий синтаксис, более читаемы и менее подвержены ошибкам. Кроме того, возможности f-строк постепенно расширяются с выходом новых версий Python.
Например, в Python 3.12 было снято ограничение на использование одинаковых кавычек в f-строках и их заполнителях.
Приведенный ниже код:
print(f'My name is {'Bond'}, {'James'} {'Bond'}')
в Python 3.11 и ранее приводит к возбуждению исключения:
SyntaxError: f-string: expecting '}'
в то время как в Python 3.12 выводит:
My name is Bond, James Bond
Также в Python 3.12 было снято ограничение на использование в заполнителях f-строк символа \.
Приведенный ниже код:
print(f'{"\n".join(["James", "Bond"])}')
в Python 3.11 и ранее приводит к возбуждению исключения:
SyntaxError: f-string expression part cannot include a backslash
в то время как в Python 3.12 выводит:
James
Bond
Начиная с Python 3.6 для форматирования строк в большинстве случаев рекомендуется использовать именно f-строки. ?
Подведем итоги
Мы рассмотрели основные способы форматирования строк в Python — оператор %, строковый метод format() и f-строки. В настоящее время любой из них можно использовать на практике. Однако %-форматирование считается устаревшим. Если вы пишите код на Python 3.5 и ниже, используйте для форматирования строк строковый метод format(). В программах на Python 3.6 и выше используйте для форматирования f-строки.
Присоединяйтесь к нашему телеграм-каналу, будет интересно и познавательно!
❤️ Happy Pythoning! ?
Комментарии (26)

tonylenc
16.07.2024 08:34+7Хотя f-строки часто удобнее и читабельнее для простых случаев, метод
format()предоставляет некоторые дополнительные возможности, такие как совместимость с более старыми версиями Python (а f-строки работают только с версии 3.6) или возможности распаковки коллекций.Например, можно распаковывать коллекции прямо при передаче аргументов:
person = ('Alice', 'Moscow', 21)print("My name is {}. I'm from {} and I'm {} years old.".format(*person))# My name is Alice. I'm from Moscow and I'm 21 years old.Или в случае со словарём:
person = {'name': 'Alice', 'city': 'Moscow', 'age': 21}print("My name is {name}. I'm from {city} and I'm {age} years old.".format(**person))# My name is Alice. I'm from Moscow and I'm 21 years old.
domix32
16.07.2024 08:34+3Сомнительная фича эти распаковки. Как минимум читать откуда ноги растут на порядок сложнее, а с учётом отсутвия жёсткой типизации ещё и ошибок можно огрести, оптимизировать или рефакторить такое тоже заметно сложнее.

milssky
16.07.2024 08:34+1Для шаблона строки почти всегда используют константу с нормальным именем. И распаковка становится очень удобной штукой
wildmathing
не знал про фигурные скобки в f строках)