Многие способы форматирования строк в Python - неужели старые (будут) устаревшими?

106

В Python есть как минимум шесть способов форматирования строки:

In [1]: world = "Earth"

# method 1a
In [2]: "Hello, %s" % world
Out[2]: 'Hello, Earth'

# method 1b
In [3]: "Hello, %(planet)s" % {"planet": world}
Out[3]: 'Hello, Earth'

# method 2a
In [4]: "Hello, {0}".format(world)
Out[4]: 'Hello, Earth'

# method 2b
In [5]: "Hello, {planet}".format(planet=world)
Out[5]: 'Hello, Earth'

# method 2c
In [6]: f"Hello, {world}"
Out[6]: 'Hello, Earth'

In [7]: from string import Template

# method 3
In [8]: Template("Hello, $planet").substitute(planet=world)
Out[8]: 'Hello, Earth'

Краткая история различных методов:

  • printf-стилевое форматирование существует с младенчества Pythons
  • TemplateКласс был введен в Python 2.4
  • formatМетод был введен в Python 2.6
  • f-strings были введены в Python 3.6

Мои вопросы:

  • Является printfустаревшим -стиль форматирование или будет устаревшим?
  • В том Template class, является ли substituteметод устаревшим или будет устаревшим? (Я не говорю о том safe_substitute, что, как я понимаю, предлагает уникальные возможности)

Похожие вопросы и почему я думаю, что они не дубликаты:

Смотрите также

геррит
источник
1
Мне нужно указать, что вы забыли Formatterурок?
Мартейн Питерс

Ответы:

14

Хотя в документации есть различные указания на то, что .formatи f-строки превосходят% строки, не существует плана, позволяющего отказаться от последних.

В коммите Проблема № 14123: Явно упомяните, что форматирование строки% в старом стиле имеет оговорки, но не исчезнет в ближайшее время. , вдохновлено проблемой. Укажите, что в настоящее время нет планов по %отмене форматирования в стиле printf , документы по -форматированию были отредактированы, чтобы содержать эту фразу:

Поскольку новый синтаксис форматирования строк более гибкий и естественно обрабатывает кортежи и словари, он рекомендуется для нового кода. Однако в настоящее время нет планов отказаться от форматирования в стиле printf .

(Акцент мой.)

Эта фраза была удалена позже в коммите Close # 4966: обновите документацию последовательности, чтобы лучше объяснить состояние современного Python . Это может показаться знаком того, что план отказа от %форматирования вернулся на карту ... но погружение в трекер ошибок показывает, что намерение было противоположным. В трекере ошибок автор коммита характеризует изменение следующим образом :

  • изменил прозу, описывающую взаимосвязь между форматированием в стиле printf и методом str.format (намеренно исключив тот факт, что первый представляет собой реальную опасность исчезновения - для нас просто непрактично серьезно думать о том, чтобы его уничтожить)

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

Более того, последнее изменение этого абзаца в марте 2017 года изменило его с этого ...

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

... к этому:

Описанные здесь операции форматирования обладают множеством причуд, которые приводят к ряду распространенных ошибок (например, неправильное отображение кортежей и словарей). Использование более новых форматированных строковых литералов, str.formatинтерфейса или строк шаблона может помочь избежать этих ошибок. Каждая из этих альтернатив обеспечивает свои собственные компромиссы и преимущества простоты, гибкости и / или расширяемости.

Обратите внимание на изменение с «помогает избежать» на «может помочь избежать», и как четкие рекомендации .formatи f-струны были заменены пушистой двусмысленной прозой о том, как каждый стиль «предоставляет свои собственные компромиссы и преимущества» . То есть не только формального отказа больше нет на картах, но и текущие документы открыто признают, что% форматирование по крайней мере имеет некоторые «преимущества» по сравнению с другими подходами.

Из всего этого я могу сделать вывод, что движение за осуждение или удаление %форматирования не только пошатнулось, но и полностью и навсегда остановлено.

Марк Эмери
источник
2
Пушистое изменение языка было добавлено, чтобы успокоить сопровождающих Mercurial (среди прочих), которые не хотели, чтобы Mercurial оставался со слишком большой базой кода, чтобы искоренить использование %. Теперь, когда от политики отказа от крупномасштабных модификаций кода отказались, их возражения тоже исчезают. В конечном итоге, поддержание обеих форм без каких-либо преимуществ, поскольку % в какой-то момент синтаксис printf все равно будет удален. Мы просто еще не знаем, когда, поэтому язык стоил смягчить.
Мартейн Питерс
@MartijnPieters Интересно. Похоже, вы хорошо осведомлены об этом решении, которого мне не хватает. Что бы это ни стоило, я думаю, что хорошо процитированный ответ от вас, в котором излагаются эти моменты (либо как новый ответ, либо как редактирование вашего существующего), будет иметь ценность.
Марк Эмери
58

Новый .format()метод призван заменить старый %синтаксис форматирования. Последнее было преуменьшено (но официально еще не устарело ). В документации метода сказано следующее:

Этот метод форматирования строк является новым стандартом в Python 3 и должен быть предпочтительнее% форматирования, описанного в разделе Операции форматирования строк в новом коде.

(Акцент мой).

Для того, чтобы поддерживать обратную совместимость и сделать переход легче, старый формат был оставлен на месте на данный момент . Из исходного предложения PEP 3101 :

Обратная совместимость

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

Обратите внимание на то, что пока не придет время отказаться от старой системы ; она не устарела, но новая система должна использоваться всякий раз, когда вы пишете новый код .

Новая система имеет то преимущество, что вы можете комбинировать кортежный и словарный подход старого средства %форматирования:

"{greeting}, {0}".format(world, greeting='Hello')

и расширяется через object.__format__() ловушки, используемой для обработки форматирования отдельных значений.

Обратите внимание, что в старой системе был %и Templateкласс, причем последний позволяет создавать подклассы, которые добавляют или изменяют его поведение. Система нового стиля имеет Formatterкласс занять ту же нишу.

Python 3 еще больше отошел от устаревания, вместо этого выдает предупреждение в разделе printfформатирования строк в стиле :

Примечание . Описанные здесь операции форматирования имеют ряд особенностей, которые приводят к ряду распространенных ошибок (например, неправильное отображение кортежей и словарей). Использование более новых форматированных строковых литералов или str.format()интерфейса помогает избежать этих ошибок. Эти альтернативы также предоставляют более мощные, гибкие и расширяемые подходы к форматированию текста.

Python 3.6 также добавил форматированные строковые литералы , которые вставляют выражения в строки формата. Это самый быстрый метод создания строк с интерполированными значениями, и его следует использовать вместо того, str.format()где вы можете использовать литерал.

Мартейн Питерс
источник
4
С его помощью Formatterвы можете создавать собственные форматы, например те, которые datetimeиспользуются объектами. Кроме того, поскольку .formatэто функция, вы можете использовать ее для более прямого создания вызываемого ленивого форматирования: например,fmt = '{} - {}'.format; fmt(a, b)
Джон Клементс
Я не понимаю, как Templateэто связано %со старой системой . В частности, состояния PEP, которые вы связываете. Хотя есть некоторое совпадение между этим предложением и string.Template, чувствуется, что каждое из них служит определенной потребности и что одно не устраняет другого. В вашем ответе может возникнуть путаница, что Templateформатирование, являющееся частью старой системы , тоже устарело.
Bakuriu
@Bakuriu: Верно, думаю, я пропустил эту часть; но на мой взгляд Formatterкласс может удовлетворить те же потребности, что и string.Template().
Мартин Питерс
1
[...]should be preferred to the % formatting[...]эта часть удалена из документации. docs.python.org/3/library/stdtypes.html#str.format
AXO
Я думаю, что этот ответ в настоящее время вводит в заблуждение; первый процитированный отрывок был удален из документации Python 3, и мне кажется довольно очевидным, что не осталось намерений отказаться от поддержки. Этот ответ по-прежнему имеет историческую ценность, но я был бы склонен изменить формулировку, чтобы избежать любых предположений о том, что устаревание все еще не решено, и отредактировать большую часть первой половины ответа, чтобы она была в прошедшем времени. Я сделаю это сам в какой-то момент, если вы не возражаете, но я подумал, что сначала прокомментирую, чтобы дать вам возможность внести такие изменения самостоятельно, если хотите.
Марк Эмери
45

%Оператор для строки форматирования не рекомендуется, и не собирается быть удалены - несмотря на другие ответы.
Каждый раз, когда этот вопрос поднимается в списке разработчиков Python, возникают сильные споры о том, что лучше, но нет споров о том, следует ли удалять классический способ - он останется. Несмотря на то, что он обозначен в PEP 3101, Python 3.1 пришел и ушел, и %форматирование все еще существует.

Заявления о сохранении классического стиля ясны: это просто, это быстро, быстро делать короткие вещи. Используя.format метода не всегда более читабельно - и почти никто - даже среди основных разработчиков не может использовать полный синтаксис, предоставленный .formatбез необходимости просматривать ссылку. Даже в 2009 году можно было получить такие сообщения: http: // mail. python.org/pipermail/python-dev/2009-October/092529.html - с тех пор тема почти не появлялась в списках.

Обновление 2016

В текущей разрабатываемой версии Python (которая станет Python 3.6) есть третий метод интерполяции строк, описанный в PEP-0498 . Он определяет новую котировку префикс f""(помимо тока u"", b""иr"" ).

Добавление к строке префикса fвызовет метод строкового объекта во время выполнения, который автоматически интерполирует переменные из текущей области в строку:

>>> value = 80
>>> f'The value is {value}.'
'The value is 80.'
jsbueno
источник
3
Гораздо лучше позволить типам реализовывать свои собственные __format__. Так , например, format(Decimal('0.1'), '.20f')против '%.20f' % Decimal('0.1'). Последний переводит Decimal в число с плавающей запятой.
Eryk Sun
2
NB. Я не спорил, что старый стиль лучше во всех отношениях - просто он короче и иногда читабельнее (а иногда и нет). Безусловно, новый способ намного более гибок.
jsbueno
Есть ли эквивалент fв Python 3?
Daniel
f-strings, Используемые выше, новая функция в языке Питон 3.6. Он не существует в предыдущих версиях и вызовет в них синтаксическую ошибку.
jsbueno
20

Последняя позиция Гвидо по этому поводу, кажется, указана здесь:

Что нового в Python 3.0

PEP 3101: новый подход к форматированию строк

Новая система для встроенных операций форматирования строк заменяет оператор форматирования строк%. (Тем не менее, оператор% по-прежнему поддерживается; он будет объявлен устаревшим в Python 3.1 и удален из языка через некоторое время.) Прочтите PEP 3101, чтобы получить полную информацию.

И сам PEP3101 , последняя модификация которого датируется (пт, 30 сентября 2011 г.), так что, я полагаю, в последнее время нет прогресса в этом.

GSP
источник
18

Глядя на более старые документы Python и PEP 3101, было сказано, что оператор% будет устаревшим и удален из языка в будущем. Следующее заявление было в документации Python для Python 3.0, 3.1 и 3.2:

Поскольку str.format () довольно новый, во многих кодах Python по-прежнему используется оператор%. Однако, поскольку этот старый стиль форматирования в конечном итоге будет удален из языка, обычно следует использовать str.format ().

Если вы пойдете в же разделу в документах Python 3.3 и 3.4, вы увидите, что этот оператор был удален. Я также не могу найти в документации каких-либо других заявлений, указывающих на то, что оператор будет устаревшим или удален из языка. Также важно отметить, что PEP3101 не подвергался модификации более двух с половиной лет (пт, 30 сентября 2011 г.).

Обновить

PEP461 Добавление% форматирования к байтам и байтовому массиву допускается и должно быть частью Python 3.5 или 3.6. Это еще один признак того, что оператор% жив и здоров.

Марван Альсаббаг
источник