Как отформатировать строку в 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