Формат строки Python: когда использовать!флаг преобразования с

в чем разница между этими 2 строковыми операторами формата в Python:

'{0}'.format(a)
'{0!s}'.format(a)

оба имеют одинаковый выход, если a - это целое число, список или словарь. Первая {0} делаешь неявное str() звонок?

источник

PS: ключевые слова: восклицание / взрыв "!с" форматирование

3 ответов


это упоминается в документации:

поле преобразования вызывает принуждение типа перед форматированием. Как правило, задание форматирования значения выполняется с помощью __format__() метод самого значения. Однако в некоторых случаях желательно принудительного типа в виде строки, перекрывая ее собственный определение форматирования. Путем преобразования значения в строку перед зову __format__() нормальная логика форматирования обходится.

два флаги преобразования в настоящее время поддерживаются:'!s', который называет str() о значении и '!r', который называет repr().

пример можно взять (опять же из документация), чтобы показать разницу:

>>> "repr() shows quotes: {!r}; str() doesn't: {!s}".format('test1', 'test2')
"repr() shows quotes: 'test1'; str() doesn't: test2"

просто сказал:

  • '{0}'.format(a) будет использовать результат a.__format__() для отображения значения
  • '{0!s}'.format(a) будет использовать результат a.__str__() для отображения значения
  • '{0!r}'.format(a) будет использовать результат a.__repr__() для отображения значения

>>> class C:
...     def __str__(self): return "str"
...     def __repr__(self): return "repr"
...     def __format__(self, format_spec): return "format as " + str(type(format_spec))
... 
>>> c = C()
>>> print "{0}".format(c)
format as <type 'str'>
>>> print u"{0}".format(c)
format as <type 'unicode'>
>>> print "{0!s}".format(c)
str
>>> print "{0!r}".format(c)
repr

относительно второго аргумента __format__ цитировать PEP 3101 "управление форматированием на основе каждого типа":

аргумент format_spec будет либо строковый объект или объект unicode, в зависимости от типа строка исходного формата. The __format__ метод должен проверить тип параметра спецификаторов, чтобы определить, следует ли возвращать строку или объект Юникод. Это ответственность __format__ способ возвращает объект соответствующего типа.


благодаря комментарию и ответу от @hjpotter92 для объяснения:

вот пример, который показывает разницу (это когда вы переопределить __format__ способ)

class MyClass:
    i = 12345
    def __format__(self, i):
        return 'I Override'

>>> obj = MyClass()

>>> '{0}'.format(obj)
'I Override'

>>> '{0!s}'.format(obj)
'<__main__.MyClass instance at 0x021AA6C0>'