Формат-спецификации f-строк: цена, ширина, выравнивание
F-строка умеет не только вставлять значение, но и оформлять его: два знака после точки у цены, ровные колонки, знак числа, нули вместо пробелов. Всё это — спецификация после двоеточия.
Редакция Питоники
В уроке 3 f-строка научилась вставлять значение в текст: f'Цена: {price} руб.'. Но значение вставилось «как есть», а в реальных задачах этого мало: цена 79.5 выглядит как 79.5, а касса ждёт 79.50, колонки таблицы едут, у чисел не видно знака. Оформлением управляет формат-спецификация — короткая запись после двоеточия внутри фигурных скобок.
Двоеточие включает оформление
Двоеточие внутри f-строки включает режим оформления: всё после него — инструкция о том, как показать значение. Самая ходовая спецификация — .2f: буква f означает «показать как десятичную дробь», а цифра перед ней — сколько знаков оставить после точки:
price = 79.5
print(f'Цена: {price:.2f} руб.')
print(f'{1/3:.4f}')
Цена: 79.50 руб. 0.3333
Спецификация не меняет само значение — только его вид в тексте: в переменной price по-прежнему лежит 79.5. Цифра задаёт точность с округлением: {1/3:.4f} превратил бесконечную треть в аккуратные 0.3333. А {2.675:.2f} даст 2.67, а не 2.68: число 2.675 в памяти компьютера не точное, и округление идёт по его реальному двоичному значению.
Ширина поля и выравнивание
Число после двоеточия задаёт ширину поля: Python отведёт под значение ровно столько символов, а лишнее заполнит пробелами. Символ выравнивания решает, к какому краю прижать значение: < — влево, > — вправо, ^ — по центру:
word = 'кот'
print(f'{word:<8}|')
print(f'{word:>8}|')
print(f'{word:^8}|')
кот |
кот|
кот |Палка | в конце показывает, где поле закончилось: слово «кот» занимает три символа, остальные пять в поле шириной 8 — пробелы. Без символа выравнивания текст прижимается влево, числа — вправо: так каждому типу удобно по умолчанию.
items = [('Хлеб', 45.0), ('Молоко', 89.9), ('Сыр', 620.0)]
for name, cost in items:
print(f'{name:<8}{cost:>10.2f}')
Хлеб 45.00 Молоко 89.90 Сыр 620.00
Классика отчётов: название прижато влево, цена — вправо, и столбцы денег выстроены по разрядам, как в чеке. Спецификации складываются: {cost:>10.2f} — поле шириной 10, два знака после точки.
Знак числа и ведущие нули
Спецификация + показывает знак всегда — и у положительных чисел тоже. А ведущие нули удобны для номеров и кодов: 06 в спецификации означает «поле шириной 6, пустоту залить нулями»:
print(f'{42:+}')
print(f'{-42:+}')
print(f'{7.5:06.2f}')
print(f'{42:05d}')
+42 -42 007.50 00042
Сценарий: прайс на три позиции
Менеджеру нужно показать список заказов так, чтобы суммы читались столбиком, а номера заказов не разъезжались. Это ровно та задача, ради которой и придуманы спецификации: каждому столбцу задают свою ширину и своё прижатие, а цифры дробной части приводят к общему виду.
orders = [('ORD-1', 'чай', 2, 240.0), ('ORD-2', 'кофе', 1, 180.5)]
for oid, name, qty, price in orders:
print(f'{oid:<7}{name:<8}{qty:>3}{price:>10.2f}')
ORD-1 чай 2 240.00 ORD-2 кофе 1 180.50
Четыре спецификации в одной строке: номер прижат влево в поле 7, название — влево в поле 8, количество — вправо в поле 3, цена — вправо в поле 10 с двумя знаками. Читать такую строку неудобно, зато результат выглядит как настоящий чек.
Полная грамматика спецификации
Спецификация — не набор случайных символов, а строгий порядок частей. Python разбирает её слева направо, и если часть пропущена, всё, что после неё, сдвигается. Полный набор выглядит так:
| Часть | Пример | Что делает |
|---|---|---|
| Заполнитель и прижатие | >10, <8, ^6 | ширина поля и сторона прижатия |
| Знак | +, | плюс всегда или пробел вместо плюса |
| Ведущий ноль | 06 | пустоту поля заливает нулями |
| Ширина | 12 | минимум столько символов на значение |
| Разделитель разрядов | , или _ | 1 234 567 вместо 1234567 |
| Точность | .2f | знаков после точки |
| Тип | d, f, x, b, s | в какой системе и виде показать |
Запомнить весь порядок не обязательно — на практике хватает трёх-четырёх частей. Но когда спецификация не срабатывает, причина почти всегда в нарушенном порядке: например, .2f нельзя поставить перед шириной, а знак + — после выравнивания.
Числа в других системах счисления
Спецификация # просит показать основание: для шестнадцатеричной системы добавляется префикс 0x, для двоичной — 0b, для восьмеричной — 0o. Это удобно для отладочных сообщений и вывода идентификаторов.
print(f'{255:#x}')
print(f'{255:#b}')
print(f'{8:#o}')
0xff 0b11111111 0o10
Разделитель разрядов
Спецификация , ставит запятые между разрядами, а _ — подчёркивания. Для денег и больших счётчиков это читается куда лучше, чем «2450000» с нулём в середине.
print(f'{1234567:,}')
print(f'{1234567:_.2f}')
1,234,567 1_234_567.00
Ширина из переменной
Внутри спецификации можно поставить ещё одни фигурные скобки — тогда ширина подставится из переменной. Это спасает, когда формат колонки задаётся в одном месте, а используется в десяти.
width = 12
print(f'|{"цена":<{width}}|')
print(f'|{"1234.50":>{width}}|')
|цена | | 1234.50|
Кстати, всё то же самое умеет и встроенная функция format: format(1234.5678, '.2f') вернёт '1234.57'. Это тот же механизм, только спецификация передаётся отдельным аргументом, а не внутри скобок. Проверить можно так:
print(format(1234.5678, '.2f'))
print(format(42, '08d'))
1234.57 00000042
Частые огрехи при оформлении
:>10вместо:>10.2f— сумма покажется как240.0, и колонка разъедется по разрядам.- Ширина поля меньше самой величины — обрезки не будет, значение вылезет за границу.
.2fна строке — ValueError: Unknown format code 'f' for object of type 'str'.- Округление
.2fидёт по двоичному значению числа:2.675станет2.67. Для денег это повод перейти на модуль decimal.
Под капотом спецификация — не магия интерпретатора, а вызов метода __format__, который есть у любого объекта в Python. Для чисел он написан на C и понимает всю грамматику, для строк — свой, а для своих классов вы можете определить его сами: тогда объект научится подставляться в f-строку по вашим правилам. Практический вывод простой: если f-строка ругается «Unknown format code», у значения просто нет нужного формат-кода.
Карточка спецификаций
| Спецификация | Пример | Результат | Что делает |
|---|---|---|---|
| .2f | f'{x:.2f}' | 79.50 | дробь с двумя знаками после точки |
| .4f | f'{x:.4f}' | 0.3333 | дробь с четырьмя знаками |
| 8 | f'{word:8}' | кот | поле шириной 8, текст влево |
| >10 | f'{x:>10}' | кот | поле шириной 10, значение вправо |
| ^8 | f'{x:^8}' | кот | значение по центру поля |
| + | f'{x:+}' | +42 | знак показывается всегда |
| 06.2f | f'{x:06.2f}' | 007.50 | ширина 6, пустота залита нулями |
Читается спецификация слева направо: выравнивание, ширина, точность, тип. Весь набор нужен не каждый день — держите под рукой эту карточку, а глубже в грамматику форматов шагает урок 12 про format(). Пока же закрепите главное: двоеточие — и цена превратилась в 79.50. Следующий урок покажет, что у строк есть и заготовки похитрее — методы регистра: lower, upper и title.
Мини-практика: три ценника
Соберите три строки ценника для прайса: название прижато влево в поле 10, цена — вправо в поле 8 с двумя знаками после точки, а скидка в процентах — влево в поле 6 со знаком плюс. Важно: спецификация + работает и для целых чисел.
goods = [('Хлеб', 45.0, 10), ('Молоко', 89.9, 0)]
for name, price, sale in goods:
print(f'{name:<10}{price:>8.2f}{sale:+5d}%')
Хлеб 45.00 +10% Молоко 89.90 +0%
Третья колонка — целое число со знаком: у хлеба скидка 10, у молока 0, но знак плюс печатается в обоих случаях, потому что спецификация + показывает знак всегда. Правда, +0% выглядит странно — в реальном прайсе для нулевой скидки условие писали бы отдельно.
Двоеточие внутри f-строки включает режим оформления: всё после него — инструкция о том, как показать значение.
Сначала предскажи ответ в голове — это главный навык программиста.
price = 45
print(f'Итого: {price:.2f} руб.')
word = 'код'
print(f'{word:>6}|')
print(f'{word:<6}|')
print(f'{2.675:.2f}')
1. Что выведет print(f'{79.5:.2f}')?
2. Что означает символ > в спецификации f'{name:>10}'?
3. Как прижать название товара к левому краю поля шириной 8?
4. Что выведет print(f'{7.5:06.2f}')?
5. Что произойдёт при выполнении f'{name:.2f}', если name = 'кот'?
6. Что делает спецификация + в f'{n:+}'?
7. Что выведет print(f'{1234567:>4.2f}')?
8. Что даёт спецификация # в f'{255:#x}'?
Даны name = 'Кружка' и price = 129.5. Выведи строку чека: название прижато влево в поле шириной 10, цена — вправо в поле шириной 8 с двумя знаками после точки. Затем выведи стоимость трёх кружек так же отформатированной в поле шириной 18.
Как вывести число с двумя знаками после запятой в Python?
В f-строке со спецификацией .2f: f'{price:.2f}' превратит 79.5 в '79.50'. Спецификация округляет значение по правилам двоичной арифметики и не меняет само число в переменной — только его текстовое представление.
Урок 3: f-строкиКак выровнять текст по колонкам в Python?
Задать ширину поля и символ выравнивания в f-строке: f'{name:<10}' — влево, f'{name:>10}' — вправо, f'{name:^10}' — по центру. Для чеков и таблиц названия прижимают влево, а числа вправо — разряды выстраиваются в столбик.
Почему f'{2.675:.2f}' даёт 2.67, а не 2.68?
Дробные числа хранятся в двоичном виде, и 2.675 в нём не точное — это чуть меньшее число, которое и округляется до 2.67. Так ведёт себя стандартное округление float в любом языке; для денежных расчётов используют модуль decimal.
Чем спецификации f-строк отличаются от метода format()?
Ничем в грамматике: после двоеточия пишется одна и та же спецификация, а format() — это более старый способ вызвать то же самое форматирование. F-строки короче и читаемее, поэтому стали стандартом с версии Python 3.6; полный разбор format() ждёт в уроке 12.
Урок 12: format() и старый процентКак вывести большое число с разделителями разрядов?
Спецификацией-запятой: f'{1234567:,}' напечатает 1,234,567. Если разделителем нужен подчёркивание, как в коде, — пишут f'{1234567:_}'. Работает и с дробными: f'{1234567:_.2f}' даст 1_234_567.00.
Можно ли задать ширину поля переменной?
Да: внутрь спецификации можно вложить ещё одни фигурные скобки — f'{"цена":<{width}}' подставит ширину из переменной width. Так формат колонки задают один раз, а используют в десяти шаблонах.
Понравился урок? Сошлитесь на него
«Двоеточие внутри f-строки включает режим оформления: всё после него — инструкция о том, как показать значение.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что дальше
Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.
Что читать дальше
Строки · Урок 3
f-строки: вставить значение в текст
f-строка вставляет значение прямо в текст: f'Привет, {name}!' — без плюсов, скобок и str(). Внутри фигурных скобок работает любое выражение Python. Учимся читать и писать их свободно.
Строки · Урок 5
Регистр: lower, upper, title
Один и тот же текст бывает написан как «Аня», «АНЯ» и «аня» — для Python это три разные строки. Знакомимся с методами регистра: lower, upper, title, capitalize и swapcase.
Строки · Урок 12
format() и старый процент: история форматирования
До f-строк текст собирали методом format, а до него — процентом. Эти способы живы в миллионах строк чужого кода: учимся читать их свободно и понимать, почему f-строки победили.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
Исключения · Урок 12
ValueError в Python: разбор строк в числа
int('восемнадцать') — тип подходящий, а значение не помещается. Разбираем сообщение invalid literal, границы int и float и честную проверку isdigit.
python int из строкиpython приведение типов строка число
openpyxl · Урок 7
Ширина столбцов и высота строк в openpyxl
Длинные названия больше не обрезаются: column_dimensions задаёт ширины столбцов, row_dimensions — высоты строк, а автоширина считается циклом по самой длинной строке.
openpyxl ширина столбцаopenpyxl высота строки
Строки · Урок 16
Выравнивание строк: ljust, rjust, center, zfill
ljust, rjust, center и zfill дотягивают строку до заданной ширины: ровные колонки прайса, заголовок по центру, номера заказов с ведущими нулями.
python выравнивание строкpython center строка