F-строки в Python: форматирование без боли и часов отладки
F-строки появились в Python 3.6 и заменили конкатенацию, format() и оператор %. Разбираем синтаксис вставок, числовые и датные спецификаторы, отладочный =, вложенные выражения и места, где f-строка ломается.

Вы собираете сообщение из пяти переменных, склеиваете их плюсами, ловите TypeError: can only concatenate str (not "int") to str и полчаса ищете, где именно число попало в конкатенацию. F-строки (formatted string literals) закрывают этот класс задач: значение подставляется прямо в текст, а форматирование задаётся спецификатором после двоеточия. Появились они в Python 3.6, а в 3.8 получили отладочный синтаксис =, в 3.12 — снятие старых ограничений парсера. Ниже — рабочие приёмы для тех, кто уже пишет на Python, но клеит строки по привычке.
Базовый синтаксис и чем он лучше альтернатив
F-строка — это литерал с префиксом f (или F), внутри которого фигурные скобки содержат выражение, а не только имя переменной. Python вычисляет выражение в момент создания строки и подставляет результат.
# Python 3.8+
user_name = "Мария"
order_id = 4821
total = 1290.5
# конкатенация: падает на числах, читается плохо
message = "Заказ №" + str(order_id) + " на сумму " + str(total) + " руб."
# f-строка: выражения прямо в тексте
message = f"Заказ №{order_id} на сумму {total} руб. для {user_name}"
# 'Заказ №4821 на сумму 1290.5 руб. для Мария'
Внутри скобок допустимо любое выражение: вызов метода, арифметика, обращение к элементу словаря.
items = {"apple": 3, "bread": 2}
print(f"Всего позиций: {len(items)}, яблок: {items['apple']}")
# Всего позиций: 2, яблок: 3
Правило одной строки: если внутри скобок появляется логика сложнее вызова метода или короткой арифметики, вынесите её в переменную выше. F-строка предназначена для подстановки, а не для вычислений.
Спецификаторы формата: числа, проценты, выравнивание
После значения через двоеточие идёт спецификатор — тот же мини-язык, что и у метода str.format(). Он решает задачи, ради которых раньше городили ручную обрезку и round().
price = 1234567.8912
print(f"{price:.2f}") # 1234567.89 — два знака после точки
print(f"{price:,.2f}") # 1,234,567.89 — разделитель тысяч
print(f"{0.1734:.1%}") # 17.3% — доля как процент
print(f"{255:#x}") # 0xff — hex с префиксом
print(f"{42:08d}") # 00000042 — дополнение нулями
Выравнивание задаётся символами <, >, ^ и шириной поля. Это то, что обычно делают через ljust()/rjust().
for name, qty in [("Хлеб", 2), ("Молоко", 12), ("Соль", 1)]:
# имя влево на 10 символов, число вправо на 4
print(f"{name:<10}{qty:>4}")
# Хлеб 2
# Молоко 12
# Соль 1
Разделитель тысяч через пробел или подчёркивание
Запятая как разделитель — англоязычный формат. Для читаемого вывода больших чисел в русском тексте берите подчёркивание либо форматируйте через locale, если нужны настоящие пробелы-разделители.
big = 1500000
print(f"{big:_}") # 1_500_000
Даты и объекты со своим форматом
Если у объекта есть метод __format__, спецификатор уходит прямо в него. У datetime это коды strftime — не нужно вызывать strftime() отдельно.
from datetime import datetime
now = datetime(2024, 3, 14, 9, 5)
print(f"{now:%d.%m.%Y %H:%M}") # 14.03.2024 09:05
Отладочный синтаксис = (Python 3.8+)
Самая частая экономия времени при отладке. Знак = внутри скобок выводит и само выражение как текст, и его значение. Это заменяет print("x =", x), где вы вечно забываете обновить подпись после переименования переменной.
width, height = 1920, 1080
print(f"{width=}, {height=}")
# width=1920, height=1080
print(f"{width * height=:_}")
# width * height=2_073_600
До Python 3.8 такого синтаксиса нет — на старом рантайме получите SyntaxError. Проверьте версию командой python --version, прежде чем закладываться на него в коде для чужого окружения.
Сравнение способов форматирования
| Способ | С какой версии | Плюс | Минус |
|---|---|---|---|
Оператор % | исторический | компактно для одной подстановки | путается на кортежах, устаревает |
str.format() | Python 2.6 | работает с шаблоном отдельно от данных | многословно, значения оторваны от мест |
| F-строка | Python 3.6 | значение видно на месте, быстрее | шаблон нельзя хранить отдельно от данных |
Разница не только в стиле. F-строка вычисляется на этапе компиляции литерала и обычно быстрее format() и % на подстановке нескольких значений — она не строит промежуточный шаблон. Но именно поэтому у неё есть граница применимости, см. следующий раздел.
Где f-строка ломается
Шаблон f-строки жёстко привязан к переменным в области видимости в момент выполнения. Это создаёт несколько ловушек.
- Внешний шаблон из файла или базы не подставится. Если текст с фигурными скобками пришёл извне (конфиг, локализация), f-строка не сработает — она вычисляется только для литерала в коде. Для таких случаев остаётся
str.format()илиTemplateиз модуляstring. - Кавычки внутри выражения. До Python 3.12 нельзя было использовать тот же тип кавычек, что и у самой строки:
f"{d["key"]}"давалSyntaxError. В 3.12 это ограничение сняли (PEP 701), но код должен запускаться и на 3.11 — тогда берите разные кавычки:f"{d['key']}". - Фигурная скобка как символ. Чтобы вывести саму скобку, удвойте её:
f"{{не выражение}}"даст{не выражение}. Забытое удвоение —ValueErrorили неожиданная подстановка. - Обратный слэш в выражении до 3.12. На версиях до 3.12 нельзя было писать
\прямо внутри скобок f-строки. Обходили через промежуточную переменную с"\n".
Типичные ошибки, которые вы увидите
SyntaxError: f-string: unmatched '['— незакрытая скобка или кавычки внутри выражения на старой версии.ValueError: Invalid format specifier— опечатка в спецификаторе после двоеточия, например пробел там, где ждали код формата.- Пустой вывод
{}в тексте вместо значения — забыли префиксf: обычная строка скобки не трогает.
Что настроить дальше
Включите линтер: flake8 с плагином или правило F541 в ruff ловят f-строки без единой подстановки — верный признак забытого или лишнего префикса. Если проект поддерживает версии старше 3.8, отладочный = и снятые в 3.12 ограничения парсера использовать нельзя — зафиксируйте минимальную версию в pyproject.toml и сверяйтесь с ней. Логирование — отдельная тема: там f-строку в вызов logging лучше не подставлять, потому что она вычисляется всегда, даже когда уровень лога отключён; это разбор для другого материала.
Редактор изображений: Убрать лишнее, заменить фон, добавить объект, расширить кадр — на вашем изображении.
Спросить за 20 ₽Источники: Python docs — Formatted string literals, PEP 701 — Syntactic formalization of f-strings
Частые вопросы
С какой версии Python работают f-строки?
А если у меня Python 3.7 и нужен вывод вида width=1920?
Почему в моём тексте выводятся сами скобки, а не значение?
Можно ли хранить шаблон f-строки в файле или базе и подставлять данные потом?
F-строки действительно быстрее, чем format() и оператор %?
Стоит ли использовать f-строки в вызовах logging?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.