Python string.format()

Основы

Не смотря на один из принципов Python, гласящий: «Должен существовать один — и, желательно, только один – очевидный способ сделать что-то», в нашем любимом языке есть аж четыре способа отформатировать строку. Так сложилось исторически.
Это второй урок цикла, посвящённого форматированию строк. В него входят:

  1. Строковый оператор форматирования
  2. Метод format()
  3. f-Строки
  4. Шаблонные строки

В данном уроке мы познакомимся с методом строки format().

В Python 3.0 появился новый метод строки – format(). Его предназначением было развить синтаксис уже имевшегося на тот момент строкового оператора форматирования. И действительно, новый способ оказался более удобным и гибким. Есть и обратная сторона: работает он медленнее, что, в некоторых ситуациях, критично, поскольку, вопреки расхожему мнению, программисты чаще сталкиваются с обработкой больших строк, чем больших чисел.

Содержание
  1. Параметры format()
  2. Возвращаемое значениеformat()
  3. Как работает format()?
  4. Базовое форматирование с format()
  5. Базовое форматирование для аргументов по умолчанию, позиционных и аргументов-ключевых слов.
  6. Форматирование чисел с format()
  7. Простое форматирование чисел.
  8. Форматирование ширины для целых чисел и чисел с плавающей точкой.
  9. Форматирование чисел со знаками.
  10. Форматирование чисел с выравниванием
  11. Форматирование чисел с выравниванием
  12. Выравнивание чисел по центру, левому и правому краю.
  13. Форматирование строк с format()
  14. Форматирование строк с полями и выравниванием.
  15. Обрезание строк.
  16. Форматирование элементов классов и словарей с format()
  17. Форматирование с атрибутами класса
  18. Форматирование элементов словаря с format().
  19. Аргументы как параметры в format()
  20. Динамическое форматирование.
  21. Дополнительные параметры форматирования с format()
  22. Форматирование по типу с format().
  23. Переопределение метода _format().
  24. Условные обозначения str() и repr() (!r и !s) с format().
  25. Appendix

Параметры format()

Методу format() можно передать любое количество аргументов двух видов:

  • Позиционные аргументы— простой список параметров. В самой строке можно указать куда вставлять какой аргумент, используя его порядковый номер (индексация начинается с нуля):

print("Второй аргумент: {1}, первый аргумент: {0}".format(1, 2,))
# Вывод:

Второй аргумент: 2, первый аргумент: 1


Если не использовать индексы явно, то Python сделает это сам, вставляя аргументы по порядку их перечисления:

print("Первый аргумент: {}, второй аргумент: {}".format(1, 2,))

# Вывод:

Первый аргумент: 1, второй аргумент: 2

  • Именованные параметры— список параметров в виде ключ=значение, доступ к которым можно получить с используя имя параметра в фигурных скобках {ключ}.

print("Первый аргумент: {первый}, "
"второй аргумент: {второй}".format(первый=1, второй=2,))
# Вывод:

Первый аргумент: 1, второй аргумент: 2


Есть несколько тонкостей, связанных с аргументами:

Если передать больше аргументов, чем указано в строке, лишние будут автоматически отброшены. Это касается, как именованных, так и позиционных параметров:

print("Первый аргумент: {}, второй аргумент: {}".format(1, 2, 3,))
print("Первый аргумент: {первый}, "
"второй аргумент: {второй}".format(первый=4, второй=5, третий=6))
# Вывод:

Первый аргумент: 1, второй аргумент: 2

Первый аргумент: 4, второй аргумент: 5


Если передать методу меньше аргументов, чем указано, интерпретатор вернёт исключение:

print("Первый аргумент: {}, второй аргумент: {}".format(1,))# Вывод:

Traceback (most recent call last):

File "C:\Users\ivand\AppData\Roaming\JetBrains\PyCharm2021.2\scratches\scratch_1.py", line 9, in <module>

print("Первый аргумент: {}, второй аргумент: {}".format(1,))

IndexError: Replacement index 1 out of range for positional args tuple

 

Process finished with exit code 1

print("Первый аргумент: {первый}, "
"второй аргумент: {второй}".format(первый=4))
# Вывод:

Traceback (most recent call last):

File "C:\Users\ivand\AppData\Roaming\JetBrains\PyCharm2021.2\scratches\scratch_1.py", line 10, in <module>

print("Первый аргумент: {первый}, "

KeyError: 'второй'

 

Process finished with exit code 1

Используя индексы, Вы можете пропускать позиционные аргументы:


print("Первый аргумент: {0}, третий аргумент: {2}".format(1, 2, 3,))
# Вывод:

Первый аргумент: 1, третий аргумент: 3


Один аргумент можно использовать в нескольких местах:

print("Первый аргумент: {0}, первый аргумент ещё раз: {0}".format(1, 2, 3,))
# Вывод:

Первый аргумент: 1, первый аргумент ещё раз: 1

Возвращаемое значение format()

Метод format() возвращает отформатированную строку.

Как работает format()?

Метод format() подставляет в строку переданные аргументы, применяя к ним указанные модификаторы формата.

Давайте рассмотрим пример:


print("Первый аргумент: {0:+06d}, "
"второй аргумент: {второй:>10b}".format(-1, 3, второй=2,))
# Вывод:

Первый аргумент: -00001, второй аргумент:         10


Что здесь происходит:

  • Сперва в строку подставляются позиционные аргументы (-1 и 3). Поскольку в строке явно указан индекс позиционного аргумента, который надо использовать ({0}), остальные игнорируются.
  • Затем подставляются именованные аргументы. В нашем случае это второй=
  • Далее к выбранным аргументам применяются модификаторы формата, указанные в фигурных скобках после двоеточия. Для первого это {+06d}, что означает «вставь число, отобрази его знак и, если его ширина меньше шести символов, дополни до шести нулями». Для второго указаны следующие модификаторы: {>10b}. Они говорят интерпретатору: «выведи число в двоичной системе исчисления, дополни до десяти символов пробелами и выровняй по правому краю».

Обратите внимание, как много всего сделано всего в одной строке. Как и в случае с регулярными выражениями, такая мощь достигается благодаря лаконичному синтаксису. Но это несёт в себе и минусы:

  1. Модификаторы плохо воспринимаются человеком
  2. Достаточно ошибиться всего в одном символе, чтоб всё пошло прахом.

Реальный кейс из моей практики: описывая необходимые изменения в XSD-схеме, упустил один пробел в шаблоне значения тега XML. Итог – полная остановка всего проекта. Будьте осторожны!

Базовое форматирование с format()

Метод format() позволяет использовать простые заполнители для форматирования.

Базовое форматирование для аргументов по умолчанию, позиционных и аргументов-ключевых слов.


# аргументы по умолчанию

print("Здравствуйте, {}. Глубина Вашего внутреннего мира {} км.".format("Изольда", 0.3))
# Вывод:

Здравствуйте, Изольда. Глубина Вашего внутреннего мира 0.3 км.

# позиционные аргументы

print("Здравствуйте, {0}. Глубина Вашего внутреннего мира {1} км.".format("Изольда", 0.3))
# Вывод:

Здравствуйте, Изольда. Глубина Вашего внутреннего мира 0.3 км.

# аргументы ключевые слова

print("Здравствуйте, {имя}. "
"Глубина Вашего внутреннего мира {км} км."
.format(имя="Изольда", км=0.3))
# Вывод:

Здравствуйте, Изольда. Глубина Вашего внутреннего мира 0.3 км.

# смешанные аргументы

print("Здравствуйте, {}. "
"Глубина Вашего внутреннего мира {км} км."
.format("Изольда", км=0.3))
# Вывод:

Здравствуйте, Изольда. Глубина Вашего внутреннего мира 0.3 км.


При использовании смешанных аргументов аргументы-ключевые слова должны идти после позиционных аргументов.

Форматирование чисел с format()

С помощью спецификаторов формата можно форматировать и числа:

Типы форматирования чисел

Тип Значение
d Десятичное число
c Символ Unicode по номеру
b Двоичный формат
o Восьмеричный формат
x Шестнадцатеричный формат (в нижнем регистре)
X Шестнадцатеричный формат (в верхнем регистре)
n То же, что и d, но использует местную настройку для разделения числа
e Экспоненциальная запись (e в нижнем регистре)
E Экспоненциальная запись (E в верхнем регистре)
f Отображать фиксированное количество знаков (по умолчанию 6)
F То же, что и f, только отображает inf как INF, а nan как NAN
g Общий формат. Округляет число до p значащих цифр (Точность по умолчанию: 6)
G Аналогично g, но переключается к E, если число очень большое
% Проценты. Делит на 100 и добавляет % в конце

Простое форматирование чисел.


# целочисленные аргументы

print("Здравствуйте, {}. "
"Глубина Вашего внутреннего мира {км:d} км."
.format("Изольда", км=0))
# Вывод:

Здравствуйте, Изольда. Глубина Вашего внутреннего мира 0 км.

# аргументы с плавающей точкой

print("Здравствуйте, {}. "
"Глубина Вашего внутреннего мира {км:f} км."
.format("Изольда", км=0.3))
# Вывод:

Здравствуйте, Изольда. Глубина Вашего внутреннего мира 0.300000 км.

# восьмеричный, двоичный и шестнадцатеричный формат

print("Здравствуйте, {}.\n"
"Глубина Вашего внутреннего мира\n"
"в двоичной/восьмиричной/шестнадцатеричной"
" системах:\n{км:b}/{км:o}/{км:x} км."
.format("Изольда", км=999))
# Вывод:

Здравствуйте, Изольда.

Глубина Вашего внутреннего мира

в двоичной/восьмиричной/шестнадцатеричной системах:

1111100111/1747/3e7 км.


Если передать аргумент не подходящего типа, Вы получите исключение:

print("Здравствуйте, {}. "
"Глубина Вашего внутреннего мира {км:d} км."
.format("Изольда", км=0.3))
# Вывод:

Traceback (most recent call last):

File "C:\Users\ivand\AppData\Roaming\JetBrains\PyCharm2021.2\scratches\scratch_1.py", line 1, in <module>

print("Здравствуйте, {}. "

ValueError: Unknown format code 'd' for object of type 'float'

 

Process finished with exit code 1

Форматирование ширины для целых чисел и чисел с плавающей точкой.

# целые числа с минимальной шириной

print("{:20d}".format(3))
# Вывод:

                   3

# ширина не работает для чисел длиннее заполнения

print("{:2d}".format(333))
# Вывод:

333

# заполнение для чисел с плавающей точкой

print("{:7.4f}".format(3.14))
# Вывод:

 3.1400

# целые числа с минимальной шириной, заполненные нулями

print("{:03d}".format(7))
# Вывод:

007

# заполнение для чисел с плавающей запятой, заполненных нулями

print("{:08.3f}".format(12.2346))

Форматирование чисел со знаками.

# показать знак

print(«{:+03d}, {:+03d}».format(7, -7))

# Вывод:

+07, -07

# показать знак —

print(«{:-03d}, {:-03d}».format(7, -7))

# Вывод:

007, -07

# показать место для знака +

print(«{: 03d}, {: 03d}».format(7, -7))

# Вывод:

07, -07

Форматирование чисел с выравниванием

Операторы <, ^, > и = используются для выравнивания в том случае, если указана конкретная ширина.

Форматирование чисел с выравниванием

Тип Значение
< Выравнивается по левому краю
^ Выравнивается по центру
> Выравнивается по правому краю
= Сдвигает знаки (+ или -) влево

Выравнивание чисел по центру, левому и правому краю.


# целые числа с выравниванием по правому краю

print("{:7d}".format(7))
# Вывод:

      7

# числа с плавающей точкой с выравниванием по центру

print("{:^7.1f}".format(3.14))
# Вывод:


3.1

# выравнивание целого числа по центру заполнено нулями

print("{:^07d}".format(3))
# Вывод:

0003000

# числа с плавающей точкой с выравниванием по правому краю и сдвигом знака

print("{:=07.1f}".format(-3.14))
# Вывод:

-0003.1


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

Форматирование строк с format()

Как и числа, строки можно форматировать с помощью format().

Форматирование строк с полями и выравниванием.

# отступ строки с выравниванием по левому краю

print("{:10}-Питончик".format("Python"))
# Вывод:

Python    -Питончик

# отступ строки с выравниванием по правому краю

print("{:>10}-Питончик".format("Python"))
# Вывод:

Python-Питончик

# заполнение строк с выравниванием по центру 
print("{:^10}-Питончик".format("Python")) 
# Вывод:

 Python  -Питончик 

# заполнение строк с выравниванием по центру 
# и '_' - символ заполнения 

print("{:_^10}-Питончик".format("Python")) 
# Вывод:

__Python__-Питончик

Обрезание строк.

# обрезание строк до двух символов

print("{:.2}-Питончик".format("Python"))
# Вывод:

Py-Питончик

# обрезание строк до двух символов и заполнение

print("{:10.2}-Питончик".format("Python"))
# Вывод:

Py        -Питончик

# обрезание строк до двух символов,

# заполнение символом «_» и выравнивание по центру

print("{:_^6.2}-Питончик".format("Python"))
# Вывод:

__Py__-Питончик

Форматирование элементов классов и словарей с format()

Python использует функцию getattr() для элементов класса в форме “.age”. А __getitem__() — для элементов словаря в форме “[index]”.

Форматирование с атрибутами класса

# определяем класс

class MyClass:
    my_int_var = 3
    my_float_var = 3.14
    my_str_var = 'Python'

# обращаемся к атрибутам объекта

print("{inst.my_str_var}-Питончик".format(inst=MyClass()))
# Вывод:
Python-Питончик

Форматирование элементов словаря с format().


# объявляем словарь

my_dict = {'my_int_var': 2, 'my_str_var': 'Python'}

# выводим значения по ключу

print("{словарь[my_str_var]}-Питончик".format(словарь=my_dict))
# Вывод:

Python-Питончик


По аналогии с классом словарь  передается в качестве аргумента.

Есть и более простой способ форматировать словари в Пайтоне — с помощью распаковки str.fromat(**mapping):

print("{my_str_var}-Питончик".format(**my_dict))
# Вывод:

Python-Питончик

Аргументы как параметры в format()

Параметры, такие как точность, выравнивание или символы заполнения можно передавать в качестве позиционных аргументов-ключевых слов.

Динамическое форматирование.

# динамический шаблон формата строки

string = "{:{заполнитель}{выравнивание}{ширина}}"

# передача кодов формата в качестве аргументов

print(string.format('Питон', заполнитель='_', выравнивание='^', ширина=9))
# Вывод:

__Питон__

# тот же фокус с позиционной подстановкой

string = '{:{}{}{}}'
print(string.format('Питон', '_', '^', 9))
# Вывод:

__Питон__

Дополнительные параметры форматирования с format()

format() также поддерживает форматирования по типам, например, для datetime или форматирование сложных чисел. Он внутренне вызывает __format__() для datetime и получает доступ к атрибутам сложных чисел.

Форматирование по типу с format().

import datetime

# datetime форматирование

current_datetime = datetime.datetime.now()
print("Сейчас: {:%d.%m.%Y %H:%M}".format(current_datetime))
# Вывод:

Сейчас: 22.12.2021 15:22

# форматирование комплексных чисел

my_complex = 3+14j
print("Реальная часть: {0.real} мнимая часть: {0.imag}".format(my_complex))
# Вывод:

Реальная часть: 3.0 мнимая часть: 14.0

Переопределение метода _format().

Можно запросто переопределить метод __format__() для любого объекта для создания собственного форматирования.

# пользовательский метод __format__()

class MyClass:

    def __init__(self):
        self.my_str_var = 'Пайтон'

    def __format__(self, format):
        if (format == 'Python'):
            return self.my_str_var
        else:
            return self.my_str_var

print("Лучший язык программирования: {:Python}".format(MyClass()))
# Вывод:

Лучший язык программирования: Пайтон

Условные обозначения str() и repr() (!r и !s) с format().

Как и __format__() можно запросто переопределять метода __str__() и __repr__() объекта.

# __str__() и __repr__() сокращенно !r и !s

# реализация для класса __str__() и __repr__()

class MyClass:

        def __init__(self):
            self.my_str_var = 'Пайтон', 'Python'

        def __str__(self):
            return self.my_str_var[0]

        def __repr__(self):
            return self.my_str_var[1]


print("Лучший язык программирования: {!r}".format(MyClass()))
print("Лучший язык программирования: {!s}".format(MyClass()))
# Вывод:

Лучший язык программирования: Python

Лучший язык программирования: Пайтон

Appendix

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


print(format(1, 'f'))
print(format(1000, '#>+10,.2f'))
print(format(1000.5368, '~>+15,.2f'))
print(format('format', '.2'))
# Вывод:

1.000000

#+1,000.00

~~~~~~+1,000.54

fo


И, в завершение темы, небольшая «пасхалка» (неочевидное поведение):

string = '{}'
print(string.format('{}').format(1, 2, 3))
string = '{{}}'
print(string.format(1, 2, 3))
string = '{{{}}}'
print(string.format(1, 2, 3))
string = '{{{{}}}}'
print(string.format(1, 2, 3))
# Вывод:

1

{}

{1}

{{}}

print('{:{}{}}'.format(1, 2, 3))
# Вывод:

1

print('{{}{}}'.format(1, 2, 3))
# Вывод:

Traceback (most recent call last):

File "C:\Users\ivand\AppData\Roaming\JetBrains\PyCharm2021.2\scratches\scratch_1.py", line 1, in <module>

print('{{}{}}'.format(1, 2, 3))

ValueError: Single '}' encountered in format string

 

Process finished with exit code 1

Оцените статью
О Python на русском языке
Добавить комментарий

Adblock
detector