Как отформатировать строку в Python. Есть ли способ лучше других? Или более эффективный? Или более безопасный?
Когда дело доходит до форматирования строки на основе шаблона, в который должны быть вставлены значения переменных, Python предлагает несколько способов выполнения этой операции. Есть ли способ лучше других? Или более эффективный? Или более безопасный? В этой статье представлены пять способов форматирования строки и попытка ответить на эти и многие другие вопросы. Он также предлагает вам рекомендации, которые помогут вам выбрать способ форматирования строк, который наиболее подходит для вашего контекста и потребностей.
1. Оператор конкатенации
Более прямой способ отформатировать строку, включающую значения переменных, - использовать оператор конкатенации +
. С одной стороны, форматирование довольно прямое, поскольку строка строится постепенно. С другой стороны, проблема в том, что вы должны преобразовывать нестроковые переменные с помощью встроенной функции str
. Вот пример, включающий date
и int
в строку:
pubdate = datetime.date(2021, 6, 10) delta = datetime.date.today() - pubdate footer = 'Published on ' + str(pubdate) + ' (' + str(delta.days) + ' days ago)'
У этого подхода есть еще две проблемы. В результате создается множество строковых объектов, по одному для каждого использования оператора +
. И это затрудняет чтение кода из-за длинных инструкций.
2.% -форматирование по старому стилю
Подход конкатенации смешивает шаблон строки и значения, которые должны быть вставлены в него. Другой подход, аналогичный функции printf
из C, заключается в использовании старой записи% -форматирования. Шаблон представляет собой строку с заполнителями, определенными символами %
, за которыми следует спецификатор аргумента, соответствующий типу значения. Значения для вставки помещаются в кортеж, записанный после строки шаблона и разделенный знаком %
:
footer = 'Published on %s (%s days ago)' % (pubdate, delta.days)
Когда нужно вставить только одно значение, его можно поставить сразу после %
, без необходимости использовать кортеж. Также можно сделать шаблон более читабельным с помощью именованных заполнителей. Затем значения помещаются в словарь, ключи которого являются именами заполнителей:
footer = 'Published on %(date)s (%(days)s days ago)' % {'date': pubdate, 'days': delta.days}
Спецификаторы формата описаны на странице Форматирование строк в стиле printf документации Python. На странице рекомендуется не использовать этот подход из-за возможных ошибок и причуд, как в документации.
3. Метод нового стиля format ()
В Python 3 был введен новый способ форматирования строк, позволяющий избавиться от синтаксиса% -форматирования. Этот подход основан на методе форматирования, который можно использовать для строковых объектов. Заполнители определяются с {}
вместо %
, и значения передаются в качестве аргументов методу:
footer = 'Published on {} ({} days ago)'.format(pubdate, delta.days)
Доступен мини-язык спецификации формата для определения того, как значения должны быть отформатированы. Спецификация должна быть указана между скобками и предлагает много мощных возможностей. При таком подходе также можно называть заполнители:
footer = 'Published on {date} ({days} days ago)'.format(date=pubdate, days=delta.days)
4. Синтаксис F-строки
В Python 3.6 стал доступен новый подход, называемый форматированными строковыми литералами (или для краткости f-strings). Такая f-строка определяется путем добавления к строковому литералу префикса f
и встраивания в него любых выражений Python с помощью фигурных скобок:
footer = f'Published on {pubdate} ({delta.days} days ago)'
Форматированные строковые литералы на самом деле являются функцией синтаксического анализатора Python, который компилирует их в эффективные операции конкатенации. Для форматирования можно использовать те же спецификаторы, что и для метода format
.
5. Шаблон строки
Пятый возможный подход состоит в том, чтобы сначала создать строковый шаблон, а затем заменить значениями заполнители, определенные символом the$
. Он основан на Template
объектах из модуля string
:
t = string.Template('Published on $date ($days days ago)') footer = t.substitute(date=pubdate, days=delta.days)
Этот способ работы проще и менее эффективен, поскольку он не поддерживает никаких спецификаторов формата. Однако это более осторожный подход, особенно при работе со строками, созданными пользователем. Проблемы безопасности действительно существуют с format
методом [1].
Все пять представленных подходов доступны в текущей версии Python, но какой из них предпочтительнее?
Первый критерий, который следует учитывать, - это время выполнения. Было проведено несколько экспериментов, которые привели к одним и тем же выводам: f-строка - более быстрый подход, а строковый шаблон - более медленный [2]. Тесты также показывают, что подход% -форматирования превосходит метод format
. Фактически, F-струны сочетают в себе элегантность последнего и более быструю методику [3].
Другой критерий, даже более важный в мире Python, - это читабельность кода. Подход с f-строкой явно более читабелен, но он может быстро стать громоздким, если вы используете его со сложными выражениями. Если шаблон не определен как литерал, рекомендуется использовать метод format
.
Наконец, последний критерий связан с безопасностью. Подходы к форматированию строк, основанные на ненадежных данных, действительно могут создавать уязвимости. Уязвимы и% -форматирование старого стиля, и метод format
[4]. Им нужна предварительная дезинфекция шаблона, если он не буквальный. Подход с использованием строкового шаблона более безопасен, но имеет ограниченные возможности. F-строки можно использовать безопасно, так как они сначала анализируются компилятором перед выполнением.
В заключение, следует отдавать предпочтение f-строкам, когда это возможно, и использовать их с ранее определенными переменными или простыми выражениями. Однако другие подходы могут использоваться в зависимости от контекста или со старыми версиями Python.
использованная литература
[1] Армин Ронахер (2016). Будьте осторожны со строковым форматом нового стиля Python, Мысли и сочинения Армина Ронахера.
[2] Олаф Горски (2020). Производительность различных методов конкатенации строк в Python - почему f-строки такие классные, Олаф Горски, инженер по продукту.
[3] Майкл Хирш (2019). Тесты Python f-string, Научные вычисления | SciVision.
[4] Збигнев Банах (2020). Что такое уязвимости форматной строки? Блог Netsparker Web Security.
Больше контента на plainenglish.io