Помните про Дзен Python и про то, как должен существовать "один и, желательно, только один - очевидный способ сделать это"? Вы удивитесь, когда узнаете, что в Python существует четыре основных способа форматирования строк!
В этой статье я покажу, как эти четыре подхода к форматированию строк работают и каковы их соответствующие достоинства и недостатки. Я также покажу вам свое "эмпирическое правило" в отношении того, как я подбираю наилучший универсальный подход к форматированию.
Сразу перейдем к делу, так как нам нужно много рассмотреть. Чтобы получить простой игрушечный пример для экспериментов, предположим, что у нас есть две представленные ниже переменные (или на самом деле константы), с которыми мы будем работать.
errno = 50159747054
name = 'Боб'
И на основе этих переменных мы хотели бы сгенерировать выходное строковое значение с сообщением об ошибке:
'Эй, Боб! Вот ошибка 0xbadc0ffee!'
Надо сказать, что такая ошибка и впрямь испортит разработчику утро понедельника! Но сегодня мы здесь собрались, чтобы обсудить форматирование строк. Поэтому приступим.
№1. "Классическое" форматирование строковых значений
Строковые значения в Python имеют уникальную встроенную операцию, к которой можно обратиться через оператор %. Оператор позволяет очень просто выполнять позиционное форматирование. Синтаксис будет знаком тем, кто работал с функцией printf в языке C. Ниже дан простой пример:
Здесь я использую спецификатор формата %s, чтобы сообщить Python, где подставить значение переменной name, представленной в виде строкового формата.
В классическом форматировании строк существуют и другие спецификации формата, служащие для того, чтобы дать вам возможность управлять вводимым строковым значением.
Ниже я использую спецификатор формата %x, чтобы преобразовать целочисленное значение в строковое и представить его как шестнадцатеричное число:
Синтаксис классического форматирования слегка изменится, если вы захотите выполнить многочисленные подстановки в одной строке. Поскольку оператор % принимает всего один аргумент, вам необходимо обернуть правую часть в кортеж, как здесь:
Кроме того, к постановкам переменных в своей форматной строке можно обращаться по имени. В этом случае в оператор % следует передать словарь с отображением имен на соответствующие им значения:
Я уверен вы спросите, почему такое форматирование в стиле printf называется "классическим" форматированием строк. Что ж, давайте расскажу. Дело в том, что оно технически было заменено на "современное" форматирование, о котором мы собираемся поговорить уже через минуту.
Но не смотря на то, что "классическому" форматированию стали придавать меньше значение, оно не было объявлено нерекомендуемым к использованию. И в последних версиях Python оно все еще поддерживается.
№2. "Современное" форматирование строковых значений.
Python 3 ввел новый способ форматирования строк, который позднее был также перенесен в Python 2.7. Такое форматирование избавляется от синтаксиса с использованием оператора % и делает синтаксис форматирования более упорядоченным.
Форматирование теперь обрабатывается вызовом метода format() со строковым объектом.
Метод format() может применяться как для выполнения простого позиционного форматирования, как в случае с оператором %:
Либо вы можете обращаться к подстановкам переменных по имени и использовать их в любом порядке, в котором вы захотите. Это довольное мощное функциональное средство языка, поскольку оно позволяет изменять порядок следования отображаемых элементов, не изменяя аргументы, переданные в функцию:
Этот пример также показывает, как изменился синтаксис форматирования целочисленной переменной в виде шестнадцатеричной строки. Теперь мы должны передавать спецификацию формата (format spec) путем добавления суффикса ":x" после имени переменной.
В Python 3 "современному" форматированию строк отдается предпочтение по сравнению с форматированием с использованием %. Однако, начиная с Python 3.6, появился еще более оптимальный способ форматирования строковых значений. И об этом способе я вам расскажу в следующем разделе.
№3. Интерполяция литеральных строк (Python 3.6+)
Python 3.6 добавляет еще один способ форматирования строк, который называется форматированными строковыми литералами (Formatted String Literal). Этот новый способ форматирования строк позволяет использовать выражения Python, которые встраиваются в строковые константы. Ниже дан простой пример, который поможет вам проникнуться:
В новом синтаксисе заложена большая мощь. Поскольку он позволяет встраивать произвольные выражение Python, вы даже можете выполнять локальные арифметические действие, как показано ниже:
Строковые литералы также поддерживают существующий синтаксис форматных строк метода str.format(). Это позволяет решать те же самые задачи форматирования, которые мы обсудили в предыдущих двух разделах:
№4. Шаблонные строки
Еще один прием форматирования строк в Python представлен шаблонными строками. Этот механизм более простой и менее мощный, но в некоторых случаях он может оказаться именно тем, что вы ищете.
Давайте взглянем на простой пример приветствия:
Здесь вы видите, что нам приходится импортировать класс Template из встроенного модуля Python string. Шаблонные строки не являются ключевым функциональным средством языка, но они обеспечиваются модулем стандартной библиотеки.
Еще одно отличие состоит в том, что такие строки не допускают спецификаторы формата. Поэтому, чтобы заставить пример со строковой ошибкой работать, мы должны сами преобразоваться целочисленный формат ошибки в шестнадцатеричное строковое значение.
Итак, какой же метод форматирования вам использовать?
Я вполне понимаю, что, имея такой широкий выбор способов форматирования своих строковых значений в Python, вы можете испытывать замешательство. Здесь не помешало бы соорудить какую-нибудь инфографику в виду блок-схемы.
Но я этого не сделаю) Вместо этого я попытаюсь все свести к простому эмпирическому правилу, которое я применяю, когда пишу на Python.
Эмпирическое правило, касающееся форматирования строк Python:
Если форматирующие строки поступают от пользователей, то используйте шаблонные строки, чтобы избежать проблем с безопасностью. В противном случае используйте интерполяцию литеральных строк (или по-простому f-строки) при условии что вы работаете с Python 3.6+, и "современное" форматирование строк - если нет.
Ключевые выводы
- Пожалуй, это удивляет, но в Python существует более одного способа форматирования строк.
- У каждого метода есть свои индивидуальные за и против. Ваш вариант применения будет влиять на то, какой метод вам следует использовать.
- Если вы затрудняетесь в выборе метода форматирования строк, попробуйте применить мое эмпирическое правило форматирования строк.