Ответ 1
!s
, а его братья !a
и !r
применяются str()
, ascii()
и repr()
соответственно до интерполяции и форматирования. Они называются флагами конверсии и являются частью Спецификации синтаксиса строки форматирования, а не спецификацией форматирования каждого поля применяется к значениям при интерполяции:
Поле преобразования вызывает тип перед форматированием. Обычно задание форматирования значения выполняется методом
__format__()
самого значения. Однако в некоторых случаях желательно принудительно форматировать тип в виде строки, переопределяя собственное определение форматирования.. Преобразуя значение в строку перед вызовом__format__()
, нормальная логика форматирования обходит.
Смелый акцент мой.
:s
применяется только к результату преобразования (или исходному объекту, если не было применено преобразование), и только если метод __format__
для типа объекта поддерживает этот параметр форматирования. Обычно этот тип форматирования поддерживает только объекты типа str
; он там как по умолчанию, главным образом потому, что Формат спецификации Mini-Language позволяет существование символа типа и потому что более старый %
printf
-форматное форматирование имело формат %s
. Если вы попытались применить тип s
к объекту, который его не поддерживает, вы получите исключение.
Используйте !s
(или !a
или !r
), когда у вас есть объект, который сам по себе не является строкой, и либо не поддерживает форматирование в противном случае (не все типы), либо будет отличаться от своего str()
, ascii()
или repr()
:
>>> class Foo:
... def __str__(self):
... return "Foo as a string"
... def __repr__(self):
... return "<Foo as repr, with åéæ some non-ASCII>"
... def __format__(self, spec):
... return "Foo formatted to {!r} spec".format(spec)
...
>>> print("""\
... Different conversions applied:
... !s: {0!s:>60s}
... !r: {0!r:>60s}
... !a: {0!a:>60s}
... No conversions: {0:>50s}
... """.format(Foo()))
Different conversions applied:
!s: Foo as a string
!r: <Foo as repr, with åéæ some non-ASCII>
!a: <Foo as repr, with \xe5\xe9\xe6 some non-ASCII>
No conversions: Foo formatted to '>50s' spec
Примечание: все форматирование, указанное спецификацией формата, несет ответственность за метод __format__
; последняя строка не применяет операцию выравнивания в спецификации форматирования >50s
, метод Foo.__format__
использовал ее только как литерал в операции форматирования (здесь используется преобразование !r
).
С другой стороны, для преобразованных значений используется метод str.__format__
, а выход выравнивается вправо в поле шириной 50 символов, заполненном пробелами слева.