четверг, 25 октября 2012 г.

Питон: еще раз форматирование

Хочу напомнить об одной занятной штуке, которую сам периодически забываю.

Как переводят дату-время в строку? Обычно так:

>>> from datetime import datetime
>>> d = datetime.now()
>>> d.strftime("%d.%m.%Y")
'25.10.2012'

А на самом деле можно и так:

>>> "{:%d.%m.%Y}".format(d)
'25.10.2012'

Как это работает?

.format разбирает строку формата и определяет параметры форматирования для аргументов. Для первого аргумента, очевидно, это %d.%m.%Y.

Это значение попадает в метод .__format__ в качестве аргумента, а результат вызова подставляется в шаблон:

>>> d.__format__("%d.%m.%Y")
'25.10.2012'

Что это дает? Можно коротко и элегантно записывать сложные шаблоны:

>>> "{} — {:%d.%m.%Y}".format("Today", d)
'Today — 25.10.2012'

То же самое работает и для других классов в datetime и т.д.:

>>> from datetime import date
>>> "{:%A}".format(date.today())
'Thursday'

Более того, никто не мешает определить .__format__ для своего класса, возвращающий строку построенную по заданному шаблону.

Только ради этого стоит переключиться со старого стиля "%s" % "abc" на новый, симпатичный и удобный.

12 комментариев:

  1. Интересно. С другой стороны, часто надо форматировать время по заданному формату, который выносят в константу и затем используют везде: datetime.now().strftime(DATETIME_FORMAT). В случае форматирования через __format__ придётся сначала создавать строку, по которой форматировать: fmt = '{{}} - {}'.format(DATETIME_FORMAT); fmt.format(datetime.now()), что не особо удобно.

    ОтветитьУдалить
    Ответы
    1. Если шаблон задается конфигурацией — то да, не очень удобно. Главная цель поста — еще раз напомнить о __format__ и о том что его можно перегружать. Дата-время — хорошая иллюстрация, как мне кажется.

      Удалить
    2. '{:{}}'.format(datetime.now(), '%d.%m.%Y') вполне нормально работает.

      Удалить
    3. Ого! Вот даже не думал, что такая вложенность возможна... Ага, я пропустил раздел "nesting arguments"

      Удалить
  2. Это не совсем по теме, но если ты поменяешь в шаблоне highlight.js 5.16 на 7.3, то питоньи вставке в статье начнут определяться как Питон, и у них будет подсвечено приглашение `>>>` :-)

    А по теме, .format(), на мой субъективный взгляд, едва ли можно считать "симпатичным" по сравнению с %, потому что он более мусорный в простых случаях. Хотя, конечно, он бесспорно мощнее.

    ОтветитьУдалить
    Ответы
    1. Не ожидал, что Blogger всё ещё помнит какой-то древний вариант профиля, вместо того, чтобы брать его из G+

      Удалить
    2. Blogger не знает о highlight.js, я его в шаблон руками добавлял. Да так там старый и остался. Про hljs в Гуглоплюсе вообще ничего не знаю.

      Удалить
  3. Зачем в шаблоне двоеточие?
    "{:"

    ОтветитьУдалить
    Ответы
    1. Разделяет field_name и format_spec в терминах документации. См. "{0:d}", "{arg:.3f}", "{pt.x:d}x{pt.y:}" и т.д.

      Удалить
  4. Для шаблонов — да. Но для коротких форматных строк старый стиль часто короче и яснее. И привычнее.

    ОтветитьУдалить
    Ответы
    1. Дело вкуса. Я сейчас .format везде использую. Поначалу было непривычно, а потом понравилось.

      Удалить