Рубрики
Без рубрики

Форматирование строк с помощью Python

Автор оригинала: Adam McQuistan.

Вступление

Рано или поздно форматирование строк становится необходимым злом для большинства программистов. Тем более в прошлом, до эпохи толстого клиентского графического интерфейса, но необходимость иметь конкретное строковое представление все еще является достаточно распространенным случаем использования. Мое первое знакомство было еще в колледже, когда у меня был профессор старой школы, который имел нечистую любовь к тому, чтобы заставить нас писать консольные приложения Java с невротическими спецификациями для вывода с помощью функции printf (...) . Одна вещь, которая была верна тогда и остается верной сейчас, заключается в том, что документация по форматированию строк (практически для всех языков) оставляет желать лучшего. Я надеюсь облегчить эту боль сегодня, написав о том, как выполнить форматирование строк в Python.

В Python существует несколько методов форматирования строк, точнее, четыре. Интересно, что это как бы идет вразрез с зерном мышления Python, что, как правило, должен быть один четкий лучший способ выполнить задачу. Однако, если вы провели какое-то разумное количество времени с языком, вы, вероятно, видели этот разрозненный набор методов и задавались вопросом: “Что со всем этим происходит?”.

Прогон четырех методов форматирования строк

Давайте начнем с наиболее распространенного метода, который использует оператор % . Я говорю “самый распространенный” просто потому, что он существует дольше всего, и вы видите его повсюду (книги, сообщения в блогах, переполнение стека и т. Д.). Чтобы использовать этот метод, вы указываете заполнитель в строке, используя %s для строк и %d для чисел.

>>> "Hello reader, welcome to the %s form of string formatting." % 'modulus'
'Hello reader, welcome to the modulus form of string formatting.'
>>>
>>> "Formatting multiple (%d, %d, %d, ...) values requires a %s." % (1, 2, 3, 'tuple')
'Formatting multiple (1, 2, 3, ...) values requires a tuple.'
>>>
>>> print("""If you prefer named placeholders for values %(one)d, %(two)d,
... %(three)d ... you can use a dict""" % {'one':1, 'two':2, 'three':3})
If you prefer named placeholders for values 1, 2,
3 ... you can use a dict

Следующий метод, который нужно охватить, – это метод str.format (...) . Это было предназначено для замены стиля % , показанного ранее. Этот метод использует фигурные скобки {} для указания того, где и как форматировать значение в строку.

>>> "Hello reader, welcome to the {} form of string formatting".format('str.format(...)')
'Hello reader, welcome to the str.format(...) form of string formatting'
>>>
>>> print("""Formatting multiple ({0}, {1}, {2}, ...) values requires  
... that you use multiple {3} brackets and optionally specify ordering
... values.""".format(1,2,3,'{}'))
Formatting multiple (1, 2, 3, ...) values requires  
that you use multiple {} brackets and optionally specify ordering
values.
>>>
>>> print("""The {language} str.format() method also allows you to use
... named parameters which help keep code {adjective}
... """.format(language='Python', adjective='concise'))
The Python str.format() method also allows you to use
named parameters which help keep code concise

Затем есть метод шаблона строки, который является классом в модуле string . Этот метод форматирования строк немного более подробен и не поддерживает спецификаторы типов (s, d, f и т. Д.), В отличие от предыдущих двух. С помощью этого метода вы указываете заполнитель в строке, префиксируя желаемое значение с помощью $ в конструкторе класса Template (...) , а затем вызываете метод substitute(...) для экземпляра объекта с именованным параметром. Этот метод гораздо менее распространен из-за его меньшей мощности и гибкости.

>>> from string import Template
>>> tmpl = Template("Hello my name is $name")
>>> tmpl.substitute(name='Adam')
'Hello my name is Adam'

Последний метод и самая последняя реализация, доступная только в Python 3.6, известна как интерполяция строк . Это имеет сходство со строкой шаблона Javascript ES6. Интерполяция строк требует, чтобы строковый литерал имел префикс f"" и позволял указывать как выражения, так и переменные непосредственно в строке, если они окружены скобками {} .

>>> method="String Interpolation"
>>> f"Hello reader, I am the {method} of formatting"
'Hello reader, I am the String Interpolation of formatting'
>>>
>>> f"With this method you can have expressions like {{1 + 1}} = {1 + 1}"
'With this method you can have expressions like {1 + 1} = 2'

Копание глубже в форматирование строк

В следующих разделах я ограничусь обсуждением только метода str.format() и метода f"" интерполяции, поскольку они являются предпочтительными методами форматирования строк. Темы, в которые я хотел бы углубиться, включают в себя:

  1. Выравнивание текста
  2. Форматирование цифр
  3. Преобразования типов

Как методы str.format () , так и методы интерполяции используют один и тот же синтаксис для определения форматирования между скобками {} , которые используют : для разделения именованных или порядковых идентификаторов слева и спецификаций форматирования справа.

Выравнивание текста

Вы можете выровнять значения в пределах заданной длины текста с помощью < , > , или ^ символы для указания выравнивания по левому краю, выравнивания по правому краю или центрирования соответственно. Затем вы следуете за этими символами с желаемой шириной символа.

Python > 2.6:

>>> left_aligned = "Left Align"
>>> center = "Centered"
>>> right_aligned = "Right Align"
>>> "{left_aligned:<15}{center:^10}{right_aligned:>15}".format(
...     left_aligned=left_aligned,
...     center=center,
...     right_aligned=right_aligned)
'Left Align      Centered     Right Align'

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

>>> "{1:<15}{0:^10}{2:>15}".format(center, left_aligned, right_aligned)
'Left Align      Centered     Right Align'

Или вы можете опустить их, если порядок параметров в format(...) совпадает с порядком {} .

>>> "{:<15}{:^10}{:>15}".format(left_aligned, center, right_aligned)
'Left Align      Centered     Right Align'

Python 3.6:

>>> f"{left_aligned:<15}{center:^10}{right_aligned:>15}"
'Left Align      Centered     Right Align'

В предыдущих примерах я неявно заполнял оставшееся пустое пространство пробелами, что является поведением по умолчанию. Однако, если это не то, что вы хотите, вы можете заполнить их чем-то другим, указав символ сразу после двоеточия.

Python > 2.6:

>>> "{:><15}|{:-^10}|{:<>15}".format(left_aligned, center, right_aligned)
'Left Align>>>>>|-Centered-|<<<

Python 3.6:

>>> f"{left_aligned:><15}{center:-^10}{right_aligned:<>15}"
'Left Align>>>>>-Centered-<<<

Числа

Форматирование чисел с плавающей запятой, содержащих десятичные знаки, – это подпруга в Python. Все, что вам нужно сделать, это следовать за двоеточием с f .

Python > 2.6:

>>> rounded_pi = 3.14
>>> "A rounded representation of Pi {:f}".format(rounded_pi)
'A rounded representation of Pi 3.140000'

Python 3.6:

>>> f"A rounded representation of Pi {rounded_pi:f}"
'A rounded representation of Pi 3.140000'

Обратите внимание, что строка имеет шесть знаков после запятой. Это происходит потому, что по умолчанию спецификатору float дается шесть мест, которые он либо заполняет нулями, либо округляет, чтобы содержать только шесть в зависимости от входных данных. Например, если я импортирую более длинную константу pi из математического модуля, вы увидите округление в действии.

Python > 2.6:

>>> from math import pi
>>> pi
3.141592653589793
>>> "A rounded representation of Pi {:f}".format(pi)
'A rounded representation of Pi 3.141593'

Python 3.6:

>>> f"A rounded representation of Pi {pi:f}"
'A rounded representation of Pi 3.141593'

Чтобы указать другую точность (количество десятичных знаков) , просто предшествуйте f на желаемое количество десятичных знаков.

Python > 2.6:

>>> "A rounded representation of Pi {:.3f}".format(pi)
'A rounded representation of Pi 3.142'

Python 3.6:

>>> f"A rounded representation of Pi {pi:.3f}"
'A rounded representation of Pi 3.142'

Другим вариантом использования форматирования для чисел с плавающей запятой является указанный процент. Это работает путем преобразования ожидаемой пропорции или отношения (0-1) в значение из 100 и обрабатывает оставшуюся десятичную часть аналогично спецификатору f с точностью по умолчанию шесть.

Python > 2.6:

>>> receptions = 17
>>> passes = 29
>>> "The completion percentage is {:.2%}".format(receptions/passes)
'The completion percentage is 58.62%'

Python 3.6:

>>> f"The completion percentage is {receptions/passes:.2%}"
'The completion percentage is 58.62%'

Хорошо, это касается большинства случаев использования чисел с плавающей запятой, но как насчет больших чисел? Python также поддерживает их форматирование, ставя запятые, чтобы увеличить читабельность больших чисел. Чтобы воспользоваться этим, просто поместите , после двоеточия.

Python > 2.6:

>>> house_price = 299999.99
>>> "The price of the house is ${:,}".format(house_price)
'The price of the house is $299,999.99'

Python 3.6:

>>> f"The price of the house is ${house_price:,}"
'The price of the house is $299,999.99'

Преобразования типов

Преобразования типов-это немного менее распространенный вариант использования, но время от времени они появляются. Основные преобразования типов для чисел следующие:

b Двоичный
o Восьмеричный
x Шестнадцатеричный
d Десятичный

Как и с другими спецификаторами формата, они работают, добавляя их после двоеточия. Надеюсь, этот общий шаблон синтаксиса форматирования становится вам ясен.

Python > 2.6:

>>> number = 157
>>> print("Binary: {:b}\nOctal {:o}\nHexadecimal: {:x}\nDecimal: {:d}".format(
...     number,
...     number,
...     number,
...     number))
Binary: 10011101
Octal 235
Hexadecimal: 9d
Decimal: 157

Python 3.6:

>>> print(f"Binary: {number:b}\nOctal {number:o}\nHexadecimal: {number:x}\nDecimal: {number:d}")
Binary: 10011101
Octal 235
Hexadecimal: 9d
Decimal: 157

Вывод

В этом кратком руководстве по форматированию строк я едва коснулся поверхности, но надеюсь, что мне удалось привести несколько конкретных примеров распространенных случаев использования, с которыми вы, вероятно, столкнетесь в своих повседневных программах на Python. Моя цель состояла в том, чтобы дать базовое объяснение синтаксиса форматирования строк и методов реализации. Отсюда вы должны быть вооружены достаточным пониманием, чтобы копаться в деталях документации. Спасибо за чтение и не стесняйтесь комментировать ниже.