Відформатовані рядкові літерали

Оновлено: 28.04.2023

formatted string literal або f-string — це рядковий літерал, який має префікс 'f' або 'F'. Ці рядки можуть містити поля заміни, які є виразами, розділеними фігурними дужками {}. Хоча інші рядкові літерали завжди мають постійне значення, форматовані рядки насправді є виразами, які обчислюються під час виконання.

Екран-послідовності декодуються як у звичайних рядкових літералах (за винятком випадків, коли літерал також позначено як необроблений рядок). Після декодування граматика вмісту рядка така:

f_string          ::=  (literal_char | "{{" | "}}" | replacement_field)*
replacement_field ::=  "{" f_expression ["="] ["!" conversion] [":" format_spec] "}"
f_expression      ::=  (conditional_expression | "*" or_expr)
                         ("," conditional_expression | "," "*" or_expr)* [","]
                       | yield_expression
conversion        ::=  "s" | "r" | "a"
format_spec       ::=  (literal_char | NULL | replacement_field)*
literal_char      ::=  <any code point except "{", "}" or NULL>

Частини рядка поза фігурними дужками трактуються буквально, за винятком того, що будь-які подвоєні фігурні дужки '{{' або '}}' замінюються відповідною одинарною фігурною дужкою. Одна відкривна фігурна дужка '{' позначає поле заміни, яке починається з виразу Python. Щоб відобразити як текст виразу, так і його значення після оцінки (корисно під час налагодження), після виразу можна додати знак рівності '='. Поле перетворення, введене знаком оклику '!' може слідувати за ним. Специфікатор формату також може бути доданий двокрапкою ':''. Поле заміни закінчується фігурною дужкою, що закривається, '}''.

Вирази у форматованих рядкових літералах розглядаються як звичайні вирази Python, оточені дужками, за кількома винятками. Порожній вираз не дозволяється, і як lambda, так і вирази присвоєння := мають бути оточені явними дужками. Вирази заміни можуть містити розриви рядків (наприклад, у рядках у потрійних лапках), але вони не можуть містити коментарів. Кожен вираз обчислюється в контексті, де з’являється відформатований рядковий літерал, у порядку зліва направо.

Якщо вказано знак рівності '=', вихідні дані матимуть текст виразу, '=' і обчислене значення. Пробіли після відкриваючої фігурної дужки '{' у виразі та після '=' зберігаються у виводі. За замовчуванням '=' надає repr() виразу, якщо не вказано формат. Коли вказано формат, за замовчуванням використовується str() виразу, якщо не оголошено перетворення '!r''.

Якщо вказано перетворення, результат обчислення виразу перетворюється перед форматуванням. Перетворення '!s' викликає str() результату, '!r'' викликає repr(), а '!a' викликає ascii().

Потім результат форматується за допомогою протоколу format(). Специфікатор формату передається в метод __format__() виразу або результату перетворення. Порожній рядок передається, якщо специфікатор формату опущено. Потім відформатований результат включається в кінцеве значення всього рядка.

Top-level format specifiers may include nested replacement fields. These nested fields may include their own conversion fields and format specifiers, but may not include more deeply nested replacement fields. The format specifier mini-language is the same as that used by the str.format() method.

Відформатовані рядкові літерали можуть бути об’єднані, але поля заміни не можуть бути розділені на літерали.

Деякі приклади відформатованих рядкових літералів:

>>> name = "Fred"
>>> f"He said his name is {name!r}."
"He said his name is 'Fred'."
>>> f"He said his name is {repr(name)}."  # repr() is equivalent to !r
"He said his name is 'Fred'."
>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal("12.34567")
>>> f"result: {value:{width}.{precision}}"  # nested fields
'result:      12.35'
>>> today = datetime(year=2017, month=1, day=27)
>>> f"{today:%B %d, %Y}"  # using date format specifier
'January 27, 2017'
>>> f"{today=:%B %d, %Y}" # using date format specifier and debugging
'today=January 27, 2017'
>>> number = 1024
>>> f"{number:#0x}"  # using integer format specifier
'0x400'
>>> foo = "bar"
>>> f"{ foo = }" # preserves whitespace
" foo = 'bar'"
>>> line = "The mill's closed"
>>> f"{line = }"
'line = "The mill\'s closed"'
>>> f"{line = :20}"
"line = The mill's closed   "
>>> f"{line = !r:20}"
'line = "The mill\'s closed" '

Наслідком спільного використання такого ж синтаксису, як і звичайні рядкові літерали, є те, що символи в полях заміни не повинні конфліктувати з лапками, які використовуються у зовнішньому форматованому рядковому літералі:

f"abc {a["x"]} def"    # error: outer string literal ended prematurely
f"abc {a['x']} def"    # workaround: use different quoting

Зворотні скісні риски не дозволені у виразах формату та призведуть до помилки:

f"newline: {ord('\n')}"  # raises SyntaxError

Щоб включити значення, у якому необхідний символ зворотної скісної риски, створіть тимчасову змінну.

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

Відформатовані рядкові літерали не можна використовувати як рядки документації, навіть якщо вони не містять виразів.

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

Дивіться також PEP 498 для пропозиції, яка додала відформатовані рядкові літерали, і str.format(), який використовує пов’язаний механізм форматування рядків.