Багато способів форматування рядків у 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Форматування стилю існує вже з дитинства пітонів
  • TemplateКлас був введений в Python 2.4
  • formatМетод був введений в Python 2.6
  • f-вряди були введені в Python 3.6

Мої запитання:

  • Чи printfзастаріле форматування формату або буде застарілим?
  • У Template class, чи є substituteметод застарілим або буде застарілим? (Я не кажу про те safe_substitute, що, як я розумію, пропонує унікальні можливості)

Подібні запитання, і чому я вважаю, що вони не копії:

Дивитися також


1
Чи потрібно мені зазначити, що ви забули Formatterклас?
Martijn Pieters

Відповіді:


14

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

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

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

(Наголос мій.)

Цю фразу було видалено пізніше, у програмі Close # 4966: перейменуйте документи послідовності, щоб краще пояснити стан сучасного Python . Це може здатися ознакою того, що %на картках знову з'явився план знеприйняття форматування ... але занурення в трекер помилок виявляє, що намір був протилежним. На трекері помилок автор комітету характеризує зміни так :

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

Іншими словами, у нас були дві послідовні зміни в %документах -форматування, які явно підкреслюють, що це не буде застарілим, а не видаленим. Документи залишаються впевненими щодо відносних достоїнств різних типів форматування рядків, але їм також зрозуміло, що %-форматування не збирається застарівати або видалятися.

Більше того, остання зміна цього пункту в березні 2017 року змінила його з цього ...

Описані тут операції з форматування демонструють різноманітні примхи, які призводять до низки поширених помилок (наприклад, неправильне відображення кортежів та словників). Використання новіших відформатованих рядкових літералів або str.formatінтерфейсу допомагає уникнути цих помилок. Ці альтернативи також забезпечують більш потужний, гнучкий і розширюваний підхід до форматування тексту.

... до цього:

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

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

З усього цього я б зауважував, що рух щодо застарілого або видалення %форматування не лише збився, але було зазнано поразки ґрунтовно і назавжди.


2
Пухнаста зміна мови була додана для того, щоб розташувати обслуговуючого персоналу Меркуріалу (серед інших), який не хотів бачити Меркуріал позаду із кодовою базою, занадто великою, щоб викорінити використання %. Тепер, коли політика "без широкомасштабних кодових мод" була знята, їхні заперечення також згасають. Зрештою, збереження обох форм без переваг, які залишаються % на певний момент, синтаксис printf все одно буде видалений Ми просто не знаємо, коли ще, і тому мова варто було знизити.
Martijn Pieters

@MartijnPieters Цікаво. Здається, ти маєш багато знань про це рішення, якого мені бракує. Оскільки це варте, я вважаю, що відповідна відповідь, у якій викладені ці пункти (як нова відповідь, чи редакція вашої існуючої), буде мати значення.
Марк Амері

58

Новий .format()метод призначений для заміни старого %синтаксису форматування. Останнє було знято з підкреслення, (але офіційно ще не застаріло ). У документації методу зазначено стільки:

Цей метод форматування рядків є новим стандартом в Python 3, і його слід віддати перевагу% форматуванню, описаному в String Formatting Operations в новому коді.

(Наголос мій).

Для того, щоб підтримувати зворотну сумісність і зробити перехід легше, старий формат був залишений на місці на даний момент . З оригіналу пропозиції 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.TemplateTemplate
Бакуріу

@Bakuriu: Так, я думаю, я пропустив цю частину; але, на мою думку, Formatterклас може задовольнити ті самі потреби, що і string.Template().
Martijn Pieters

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-O жовтня/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.'

3
Набагато приємніше дозволити типам реалізувати свої власні __format__. Так , наприклад, format(Decimal('0.1'), '.20f')проти '%.20f' % Decimal('0.1'). Останній примушує Десяткові до поплавця.
Ерик Вс

2
NB. Я не заперечував, що старий стиль є кращим в усіх відношеннях - просто він коротший, а іноді і легше читабельний (а іноді й ні). Звичайно, новий спосіб набагато гнучкіший.
jsbueno

Чи існує еквівалент для fPython 3?
Даніель

Як f-stringsописано вище, це нова функція в мові на Python 3.6. Він не існує в попередніх версіях і призведе до синтаксичної помилки на них.
jsbueno

20

Тут схоже вказується остання позиція Гідо щодо цього:

Що нового в Python 3.0

PEP 3101: Новий підхід до форматування рядків

Нова система для вбудованих операцій форматування рядків замінює оператор форматування рядків%. (Однак оператор% все ще підтримується; він буде застарілим у Python 3.1 та буде видалений з мови на деякий пізній час.) Прочитайте PEP 3101 для повного вибору.

І сам PEP3101 , який має останню зміну, що датується (пт, 30 вересня 2011 р.), Тому, мабуть, жодного прогресу, як пізніше, не було.


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. Це ще одна ознака того, що оператор% живий і брикається.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.