format() и старый процент: история форматирования
До f-строк текст собирали методом format, а до него — процентом. Эти способы живы в миллионах строк чужого кода: учимся читать их свободно и понимать, почему f-строки победили.
Редакция Питоники
f-строки из уроков 3 и 4 — не первый способ форматирования в Python, а третий. До них был метод format() (версия 2.6), а ещё раньше — оператор процент (времена Python 2). Разбираемся с обоими: не для того, чтобы писать по-старому, а чтобы свободно читать чужой код и старые туториалы — их в сети большинство.
format(): шаблон с фигурными скобками
Идея format: строка-шаблон с фигурными скобками-пустотами и аргументы, которые в них подставляются. Фигурные скобки без номера заполняются по порядку, с номером {0} — по индексу аргумента, с именем {city} — по ключевому слову. Одна и та же заготовка-шаблон переиспользуется с разными данными — в этом format всё ещё полезен сегодня.
print('{}, {}!'.format('Привет', 'мир'))
print('{1} важнее, чем {0}'.format('объём', 'качество'))
template = 'Доставка в {city}: {days} дн.'
print(template.format(city='Казань', days=3))
print(template.format(city='Сочи', days=5))
Привет, мир! качество важнее, чем объём Доставка в Казань: 3 дн. Доставка в Сочи: 5 дн.
Последние две строки — главная фишка format: шаблон сохранён в переменную и переиспользуется. f-строка так не умеет: она подставляет значения в момент написания. Если нужен многократный шаблон — format до сих пор лучший выбор.
Легаси: оператор процент
Самый старый стиль пришёл из языка C: слева строка с метками-процентами, справа после знака % — значения. %s подставляет строку, %d — целое число, %f — дробное. Метки не нумеруются — подстановка строго по порядку.
name = 'Олег'
score = 87
print('Игрок: %s, очки: %d' % (name, score))
print('Точность: %.1f%%' % 99.5)
Игрок: Олег, очки: 87 Точность: 99.5%
Почему f-строки победили
Сравните один и тот же текст тремя способами — и станет видно, за что f-строки забрали победу: значение стоит прямо на месте подстановки, а не где-то после строки.
city, days = 'Казань', 3
print('Доставка в {}: {} дн.'.format(city, days))
print('Доставка в %s: %d дн.' % (city, days))
print(f'Доставка в {city}: {days} дн.')
Доставка в Казань: 3 дн. Доставка в Казань: 3 дн. Доставка в Казань: 3 дн.
| Стиль | Вид | Статус |
|---|---|---|
| f-строка | f'Доставка в {city}' | Современный стандарт — пишем так |
| format() | '...{}'.format(x) | Нужен переиспользуемый шаблон |
| Процент % | '...%s' % x | Легаси — только читать |
Итог урока: новый код пишем f-строками, многократные шаблоны — format(), а процентный стиль распознаём глазами — он ещё десятилетие будет попадаться в старых проектах и статьях.
Как отформатировать строку в Python: три способа
Форматирование нужно, чтобы вставить в текст значение, которое вычислилось в программе: цену, количество, имя, дату. В Python есть три способа это сделать, и разница между ними — не в результате, а в том, где стоит значение. В f-строках оно стоит на месте подстановки, в format() — в аргументах метода, в процентном стиле — справа от строки. Это не мелочь: в многошаблонном коде место значения определяет, читается ли код.
city, days = 'Казань', 3
print('Доставка в {}: {} дн.'.format(city, days))
print('Доставка в %s: %d дн.' % (city, days))
print(f'Доставка в {city}: {days} дн.')
Доставка в Казань: 3 дн. Доставка в Казань: 3 дн. Доставка в Казань: 3 дн.
Три строки дают одинаковый вывод, и это важно: выбор между ними — не про результат, а про поддерживаемость. Смотрите на первую строку: чтобы понять, что подставится в «{}», надо прыгнуть вниз до аргументов. Во второй — ещё дальше, за скобки. В третьей всё видно на месте. Правило простое: если значения известны в момент написания строки — берите f-строку.
format(): подстановка по индексу и по имени
Внутри format() пустые скобки заполняются по порядку. Но можно указать номер — {0}, {1} — и тогда порядок в вызове не важен, а один аргумент можно подставить несколько раз. А можно назвать поле — {city} — и передать его ключевым словом. Именованная подстановка — самая читаемая форма, когда полей больше двух.
print('{}, {}!'.format('Привет', 'мир'))
print('{1} важнее, чем {0}'.format('объём', 'качество'))
template = 'Доставка в {city}: {days} дн.'
print(template.format(city='Казань', days=3))
print(template.format(city='Сочи', days=5))
Привет, мир! качество важнее, чем объём Доставка в Казань: 3 дн. Доставка в Сочи: 5 дн.
Обратите внимание на последние две строки: заготовка template описана один раз, а заполнена дважды разными данными. Это и есть главный сценарий для format() — он оправдывает себя, когда один текст уходит в разные места.
data = {'city': 'Казань', 'days': 3}
print('Доставка в {city}: {days} дн.'.format(**data))
print('{0} / {1}'.format(*data.values()))
Доставка в Казань: 3 дн. Казань / 3
Двойная звёздочка в format(**data) — это распаковка словаря в именованные аргументы. Работает, но читается тяжело, и при опечатке в ключе вы получите KeyError в неожиданном месте. Альтернатива — format_map(data), который берёт словарь целиком и не требует распаковки: 'Доставка в {city}: {days} дн.'.format_map(data). Ещё аккуратнее — f-строка со словарём: f'Доставка в {data[city]}'.
Формат-спецификации: то же, что в f-строках
После двоеточия в format() пишется спецификация — тот же язык, что и в f-строках из урока 4. {:.2f} — два знака после запятой, {:>10} — выравнивание вправо в поле шириной 10. Язык спецификаций f-строки унаследовали как раз от format(), поэтому, выучив один, выучили оба.
print('{:.2f}'.format(3.14159))
print('{:>10}'.format('право'))
print('{:<10}|'.format('лево'))
print('{:^10}|'.format('центр'))
3.14
право
лево |
центр |Выравнивание — самая полезная спецификация на практике. {:>10} прижимает текст к правому краю поля, {:<10} — к левому, {:^10} — по центру. Вертикальная черта в конце нужна, чтобы увидеть, где заканчивается поле: без неё пробелы невидимы. Это тот же приём, что и в уроке про ljust и rjust, только записанный в виде спецификации.
| Спецификация | Что делает | Пример |
|---|---|---|
{:.2f} | два знака после запятой | 3.14159 → '3.14' |
{:>10} | выравнивание вправо в поле 10 | 'право' → ' право' |
{:<10} | выравнивание влево | 'лево' → 'лево ' |
{:^10} | выравнивание по центру | 'центр' → ' центр ' |
{:,} | разделитель тысяч | 1234567 → '1,234,567' |
{:+d} | явный знак плюса | 5 → '+5' |
{:08d} | ведущие нули до ширины 8 | 42 → '00000042' |
Легаси: стиль с процентом
Самый старый способ — оператор %. Он пришёл из языка C, и в нём метки не нумеруются: %s означает строку, %d — целое, %f — дробное, а значения перечисляются справа в кортеже. При нескольких метках скобки обязательны. Отдельно стоит помнить, что сам процент печатается как %%.
name = 'Олег'
score = 87
print('Игрок: %s, очки: %d' % (name, score))
print('Точность: %.1f%%' % 99.5)
Игрок: Олег, очки: 87 Точность: 99.5%
Этот стиль живёт в миллионах строк чужого кода, и читать его нужно уметь. Но писать новое на % я бы не стал: там невозможно вызвать метод, нельзя вставить выражение с пробелами без скобок, а любая ошибка в количестве аргументов падает в рантайме с невнятным сообщением. Процентный стиль — это «понять и починить», а не «писать».
Что выбрать: шпаргалка
- f-строка — стандарт современного Python: значения известны на месте, код читается сверху вниз.
format()— шаблон живёт отдельно от данных: письма, отчёты, конфиги, переиспользуемые заготовки.- Именованная подстановка
{name}— когда полей больше двух и важно, чтобы было видно, что куда попадёт. - Процент
%— только для чтения чужого легаси-кода; в новом коде не пишется. - Спецификации после двоеточия (
.2f,>10,,) работают одинаково в format() и в f-строках.
Отдельно отмечу format() в местах, где f-строка невозможна: имя файла или ключа словаря строится в рантайме. Тогда шаблон приходится хранить в переменной — и format() с именованной подстановкой становится единственным разумным вариантом. Например, генерация конфигурационного файла: имя ключа заранее неизвестно, а заполнить его нужно.
И последняя практическая деталь: в f-строках внутри скобок можно писать любые выражения, включая вызовы методов и словарные ключи с кавычками другого типа. В старом %-стиле для вызова метода нужно писать %(name)s со словарём — отсюда все эти % в старых логах. Разница в читаемости очевидна.
Форматирование чисел: цифры после запятой и разделители
Отдельно от шаблонов стоит форматирование чисел — то, что чаще всего нужно в отчётах. Тут есть подвох, на котором спотыкаются: float не хранит точные десятичные значения, и при сложении копятся ошибки.
price = 1234.5
print(f'{price:.2f}')
print(f'{price:,.2f}')
print(f'{price:.0f}')
print(f'{1234567:,}')
1234.50 1,234.50 1234 1,234,567
Спецификация .2f — два знака после запятой, , — разделитель тысяч (пробел или запятая, зависит от локали), .0f — ноль знаков после запятой с округлением. Для денег в Python есть ещё и модуль decimal, который считает точно, — но это уже не строки, а отдельная тема.
И последнее. Форматирование — это про вид, а не про данные. Отформатированная строка '1 234,50' не годится для повторного разбора: это уже текст, и чтобы получить из него число, его придётся снова чистить. Храните числа числами и форматируйте только в момент показа человеку. Тот же принцип, что и с выравниванием колонок.
Сначала предскажи ответ в голове — это главный навык программиста.
print('{0} {0} {1}!'.format('ха', 'ха-ха'))
print('Итого: %d руб.' % 1234.9)
print('{:.1f}'.format(7.25))
1. Что подставится в '{} и {}'.format('соль', 'сахар')?
2. Что делает {1} в шаблоне '{1} и {0}'.format('a', 'b')?
3. Что подставит %d в 'Очки: %d' % (87.6,)?
4. Как напечатать сам знак процента в легаси-стиле?
5. Когда format() всё ещё лучше f-строки?
6. Как в format() подставить одно и то же значение дважды?
7. Что вернёт '{:.2f}'.format(3.14159)?
8. Что произойдёт при '{city}'.format_map({'citi': 'Казань'})?
Оформите заготовку-шаблон ticket = 'Рейс {flight}: {city}, посадка {gate}' и напечатайте её с данными flight='SU-101', city='Сочи', gate='5'. Затем тем же методом выведите 'Рейс SU-202: Казань, посадка 2'.
Какой способ форматирования использовать в новом коде?
f-строки — во всех случаях, где значения известны на месте написания. format() — когда нужен сохраняемый шаблон (письма, отчёты по заготовке). Процентный стиль в новом коде не пишут.
Почему f-строки нельзя сохранить как шаблон?
f-строка вычисляется сразу при создании: если city не определена — упадёт на месте. format же возвращает незаполненный шаблон с пустотами, а данные подставляются вызовом. Это разные моменты жизни строки.
Какой способ форматирования использовать в новом коде?
f-строки — во всех случаях, где значения известны на месте написания. format() — когда нужен сохраняемый шаблон (письма, отчёты по заготовке). Процентный стиль в новом коде не пишут, но читать его нужно: он встречается в старых проектах и статьях.
Урок 3: f-строкиПочему f-строки нельзя сохранить как шаблон?
f-строка вычисляется сразу при создании: если city не определена — упадёт на месте. format же возвращает незаполненный шаблон с пустотами, а данные подставляются вызовом. Это разные моменты жизни строки: шаблон может пережить десятки заполнений.
Что означают %r и %a в чужом коде?
Та же идея, что %s, но подставляется repr-представление объекта (с кавычками и экранированием) — удобно для отладочных логов. %a работает как %r, но с escape-последовательностями в ASCII-виде. Встречается в старых логах и тестах.
Как передать в format() данные из словаря?
Двойной звёздочкой: '{city}'.format(**data) — словарь распакуется в именованные аргументы. Чище и без распаковки — format_map(data), который берёт словарь целиком: '{city}: {days}'.format_map(data). Оба способа упадут с KeyError, если в шаблоне опечатка в имени поля.
Понравился урок? Сошлитесь на него
«f-строки из уроков 3 и 4 — не первый способ форматирования в Python, а третий.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что дальше
Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.
Что читать дальше
Строки · Урок 4
Формат-спецификации f-строк: цена, ширина, выравнивание
F-строка умеет не только вставлять значение, но и оформлять его: два знака после точки у цены, ровные колонки, знак числа, нули вместо пробелов. Всё это — спецификация после двоеточия.
Строки · Урок 13
Экранирование и сырые строки
Как напечатать кавычку внутри кавычек и путь Windows, который не ломается? Знакомимся с обратным слэшем — символом, который меняет смысл следующего символа.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
openpyxl · Урок 7
Ширина столбцов и высота строк в openpyxl
Длинные названия больше не обрезаются: column_dimensions задаёт ширины столбцов, row_dimensions — высоты строк, а автоширина считается циклом по самой длинной строке.
openpyxl высота строкиформатирование excel python
Datetime · Урок 4
strftime: дата превращается в строку
Объект даты хорош для вычислений, а человеку нужна строка «21.10.2026». Один метод strftime и горстка кодов — и дата принимает любой вид.
python strftime форматформат даты python
Строки · Урок 3
f-строки: вставить значение в текст
f-строка вставляет значение прямо в текст: f'Привет, {name}!' — без плюсов, скобок и str(). Внутри фигурных скобок работает любое выражение Python. Учимся читать и писать их свободно.
f строки pythonf строки в python