Сообщить об ошибке.

Форматированные строки. f-строки в Python.

"F-строки" обеспечивают краткий, читаемый способ включения значения выражений Python внутри строк. В исходном коде Python форматированная строка или по другому f-string - это буквальная строка с префиксом 'f' или 'F', которая содержит выражения внутри фигурных скобок {}. Выражения заменяются их значениями.

Escape-последовательности декодируются как в обычных строковых литералах, за исключением случаев, когда литерал также помечается как необработанная строка r'string'.

Части строки вне фигурных скобок обрабатываются буквально, за исключением того, что любые двойные фигурные скобки {{ или }} заменяются соответствующей одиночной фигурной скобкой. Одна открывающая фигурная скобка { обозначает поле замены, которое начинается с выражения Python. После выражения может быть поле преобразования, введенное восклицательным знаком !. Спецификатор формата также может быть добавлен, введенный двоеточием :. Поле замены заканчивается закрывающей фигурной скобкой }.

Выражения в форматированных строках рассматриваются как обычные выражения Python, окруженные круглыми скобками, за некоторыми исключениями:

  • Пустое выражение недопустимо.
  • Как лямбда-выражения, так и выражения присваивания := должны быть заключены в явные круглые скобки.
  • Выражения замены могут содержать разрывы строк, например в строках с тройными кавычками, но они не могут содержать комментарии.
  • Каждое выражение вычисляется в контексте, где отображается форматированный строковый литерал, в порядке слева направо.

Если указаны преобразования (!o или !a или !r) , то перед форматированием вычисляется результат преобразования. Затем результат форматируется с помощью протокола str.format(). Спецификатор формата передается в метод __format__() выражения или результата преобразования. Отформатированный результат затем включается в конечное значение всей строки.

Спецификация формата Mini-Language совпадает с языком, используемым во встроенной функции format().

Форматированные строки могут быть объединены, но поля замены не могут быть разделены между литералами.

Спецификатор '=' в f-строках:

Для самостоятельного документирования выражений и отладки в Python-3.8.1 добавлен спецификатор '=' к f-строкам. F-строка, такая как f'{expr=}', расширится до текста выражения и знака равенства, а затем представления вычисляемого выражения. Например:

>>> user = 'eric_idle'
>>> member_since = date(1975, 7, 31)
>>> f'{user=} {member_since=}'
# "user='eric_idle' member_since=datetime.date(1975, 7, 31)"

Обычные спецификаторы формата f-string позволяют более точно контролировать способ отображения результата выражения:

>>> delta = date.today() - member_since
>>> f'{user=!s}  {delta.days=:,d}'
# 'user=eric_idle  delta.days=16,075'

Спецификатор = будет отображать все выражение, чтобы можно было показать вычисления:

>>> print(f'{theta=}  {cos(radians(theta))=:.3f}')
theta=30  cos(radians(theta))=0.866

Общие примеры форматирования вывода f-строкой.

>>> name = 'Fred'
>>> f'He said his name is {name!r}.'
# 'He said his name is 'Fred'.'

# repr() является эквивалентом '!r'
>>> f`He said his name is {repr(name)}.`
# `He said his name is 'Fred'.`

# Вложенные поля
>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal("12.34567")
>>> f`result: {value:{width}.{precision}}`
'result:      12.35'

Символы в полях замены не должны конфликтовать с кавычками, используемыми во внешнем форматированном строковом литерале:

>>> a = {'x': 120}
>>> f'abc {a['x']} def'
#   File "<stdin>", line 1
#     f'abc {a['x']} def'
#               ^
# SyntaxError: invalid syntax

# Используйте различные кавычки
f"abc {a['x']} def"
# 'abc 120 def'

Обратные косые черты не допускаются в выражениях формата и вызовут ошибку:

>>> f'newline: {ord("\n")}'
#   File "<stdin>", line 1
# SyntaxError: f-string expression part cannot include a backslash

Чтобы включить значение, в котором требуется экранирование обратной косой черты, создайте временную переменную.

>>> newline = ord('\n')
>>> f'newline: {newline}'
# 'newline: 10'

Форматированные строковые литералы нельзя использовать в качестве строк документации, даже если они не содержат выражений.

>>> def foo():
...     f'Not a docstring'
...
>>> foo.__doc__ is None
True

Поддержка спецификации формата Mini-Language.

>>> b = 2999
>>> pi = 3.1415926
>>> f'Pi={pi:.3f}, b={b:*^11.2f}'
# 'Pi=3.142, b=**2999.00**'

>>> print("\n".join(f'{a:{a}<{a}}' for a in range(1, 6)))
# 1
# 22
# 333
# 4444
# 55555

# форматирование процентов
>>> perc = 34 / 87
>>> perc
# 0.39080459770114945
>>> f"Процентное отношение: {perc:%}"
# 'Процентное отношение: 39.080460%'
>>> f"Процентное отношение: {perc:.2%}"
# 'Процентное отношение: 39.08%'

Как добавить отступы к F-строке, выравнивание.

>>> greetings = "hello"
# отступы справа и слева
>>> f"{greetings:>10}"
# '     hello'
>>> f"{greetings:<10}"
# 'hello     '

# выравнивание чисел
>>> a = "1"
>>> b = "21"
>>> c = "321"
>>> d = "4321"
>>> print("\n".join((f"{a:>10}", f"{b:>10}", f"{c:>10}", f"{d:>10}")))
#          1
#         21
#        321
#       4321

# выравнивание по середине
>>> hello = "world"
>>> f"{hello:^11}"
# '   world   '
>>> f"{hello:*^11}"
# '***world***'

Форматирование числа с помощью запятых в качестве десятичного разделителя.

>>> big_num = 1234567890
>>> f"{big_num:,}"
# '1,234,567,890'

>>> num = 2343552.6516251625
>>> f"{num:,.3f}"
# '2,343,552.652'

Как отформатировать число в экспоненциальном представлении.

>>> num = 2343552.6516251625
>>> f"{num:e}"
# '2.343553e+06'
>>> f"{num:E}"
# '2.343553E+06'
>>> f"{num:.2e}"
# '2.34e+06'
>>> f"{num:.4E}"
# '2.3436E+06'

Использование спецификатора целочисленного формата.

>>> number = 1024
>>> f"{number:#0x}"
'0x400'

Использование условного if-else в F-строке

>>> a = 10
>>> b = 5
>>> f"{a if a > b else b}"
# `10`
>>> f"{a if a < b else b}"
# `5`

Использование спецификатора формата даты.

>>> import datetime
>>> today = datetime.datetime(year=2021, month=1, day=27)
>>> f`{today:%B %d, %Y}`
'January 27, 2021'

>>> now = datetime.datetime.now()
>>> ten_days_ago = now - datetime.timedelta(days=10)
>>> f'{ten_days_ago:%Y-%m-%d %H:%M:%S}'
# '2020-10-13 20:24:17'
>>> f'{now:%Y-%m-%d %H:%M:%S}'
# '2020-10-23 20:24:17'

F-строки нельзя использовать как шаблоны str.format().

>>> tmp = "R: {r}\nG: {g}\nB: {b}"
>>> rgb = {'r': 123, 'g': 145, 'b': 255}
>>> print(tmp.format(**d))
# R: 123
# G: 145
# B: 255

>>> tmp = "Шаблон строки: {}"
>>> line = "Привет"
>>> tmp.format(line)
# 'Шаблон строки: Привет'