Форматирование строк в Python 2 использовало оператор % по модулю. Python 3 был выпущен в 2008 году и включал альтернативы форматированию строк: str.format(). Перенесемся в 2016 год, когда Python 3.6 выпустил форматированные строковые литералы (или f-строки).

Может показаться иконоборчеством утверждение, что строки str.format и f не всегда предпочтительнее старого стиля, но в самой документации Python говорится, что старый стиль может быть лучше в таких случаях, как ведение журнала. Этот пост в блоге объяснит, почему вы не должны использовать новое форматирование строк при ведении журнала.

Когда использовать новое форматирование строки вместо старого форматирования

Большинство считает F-строки более удобными, чем оператор %, и, возможно, их легче читать. Они также более гибкие и могут использоваться для интерполяции выражений Python в строку.

Как гласит дзен Python: читабельность имеет значение. Новый инструмент форматирования строк Python — отличный способ улучшить читаемость. Синтаксис очень похож на существующий синтаксис форматирования строк, но есть некоторые существенные отличия:

# old style. like printf in C
print("Hello, %s!" % "world")
print("The answer is %d" % 42)
print("%f + %" = %" % (1, 2, 3))

Вы также можете использовать метод format() для форматирования строк. Это обеспечивает более гибкий синтаксис и позволяет использовать спецификации форматирования:

print("Hello, {0}!".format("world"))
print("The answer is {0}".format(42))
print("{0} + {1} = {2}".format(1, 2, 3)

Строки шаблона позволяют встраивать код Python непосредственно в ваши строки, что может быть очень полезно для сложных задач форматирования:

import datetime
t = datetime.date(2016, 1, 1)
print("Today is {t.day}/{t.month}/{t.year}".format(t=t))

Новый подход к форматированию строк имеет несколько преимуществ:

  • Он более гибкий и простой в использовании.
  • Он поддерживает именованные аргументы, которые могут упростить чтение кода.
  • Он поддерживает сложные объекты (такие как списки и словари), чего нет в старом подходе оператора %.

Старый подход с оператором % может быть предпочтительнее при работе с устаревшим кодом, потому что стабильно плохое предпочтительнее непостоянно хорошего, или (страшно подумать) библиотека, которая все еще поддерживает Python 2.7. Но в целом по возможности лучше использовать новый подход к форматированию строк.

В защиту старого форматирования строк

Старый стиль форматирования строк может быть предпочтительнее в соответствии с Документацией по регистрации Python.

Вход в Python 3

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

Самый простой способ настроить ведение журнала — вызвать функцию basicConfig(). Это настроит модуль ведения журнала с набором параметров по умолчанию. После настройки модуля ведения журнала вы можете использовать различные функции журнала для создания сообщений журнала. Наиболее часто используемые функции журнала — это debug, info, warning, error и exception. Каждая функция принимает строковый аргумент, который может быть передан в журнал (опять же, в зависимости от конфигурации).

Функция debug используется для сообщений отладки, помогающих разработчику при разработке кода, а функция info предназначена для сообщений, помогающих разработчику понять, как код ведет себя в производственной среде. Функции warning, error и exception используются для регистрации проблем возрастающего уровня серьезности.

Все эти функции принимают необязательный второй аргумент, словарь дополнительной информации, которая будет регистрироваться вместе с сообщением.

Старый против нового при регистрации

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

Форматирование аргументов сообщения откладывается до тех пор, пока его нельзя будет избежать.

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

logger.debug("encountered %s", foo)  # old style

vs

logger.debug(f"encountered {foo}")  # f string

Предположим, что конфигурация ведения журнала выше, чем отладочная (поэтому вызовы debug не отправляются в журнал). В первой версии окончательная строка не будет вычисляться (поскольку обработчик ведения журнала будет игнорировать вызовы ведения журнала отладки), а во второй версии строка вычисляется немедленно. Как говорят документы:

Возможно, вы захотите избежать этого, если регистратор просто выбросит ваше событие.

Причина, по которой модуль ведения журнала предлагает это, заключается в том, что могут быть случаи, когда оценка строк требует больших ресурсов: возможно, foo представляет набор запросов с ленивой оценкой ORM, и оценка строки заставит базу данных читать. Было бы обидно, если бы соблюдение кода негативно повлияло на систему. Если ведение журнала снижает производительность приложения, разработчики будут использовать его меньше, а это снизит их производительность как разработчиков.

Улучшите свой код

Code Review Doctor — это инструмент сканирования кода, который предлагает исправления Python и Django прямо в вашем запросе на включение:

Проверьте свои пулл-реквесты GitHub или Bitbucket, сканируйте всю кодовую базу бесплатно онлайн или подпишитесь на нас в Twitter.