Подтвердить что ты не робот

Использование! S vs.: s для форматирования строки в Python

Мне действительно интересно узнать строку формата :s в Python 3. Документация говорит !s преобразование и что :s - format_spec.

Он также говорит, что !s применит str(), но ничего не говорит о :s. Я думаю, что между ними нет существенной разницы, но я хочу быть уверенным. Может ли кто-нибудь прояснить их?

Пример кода:

print("{!s}".format("this"))
print("{:s}".format("that"))
# I want to be sure that these two are processed identically internally

Это все еще запутанно, но позвольте мне заручиться своими словами (непрофессиональными).

  • type("whatever".format) всегда str.
  • Используйте !s, если вы хотите преобразовать объект в str перед форматированием.
  • :s означает, что объект (или преобразованный объект) будет обрабатываться как str во время некоторого внутреннего процесса форматирования. Это значение по умолчанию format_spec.

Здесь что-то не так?

4b9b3361

Ответ 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 символов, заполненном пробелами слева.

Ответ 2

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

В (насколько я могу) члены непрофессионала:

  • Отсутствие или наличие флага преобразования указывает тип значения, которое мы собираемся форматировать, и, по степени, кто __format__ мы будем звонить. Как указывает Марджин, используя это, мы можем обойти определенное поведение и рассматривать значение более универсально (например, строку). Он поставляется в трех разных вариантах, которые соответствуют трем различным способам, которые объект может выбрать для представления себя как строки.
  • Спецификатор типа в сочетании с другими спецификаторами указывает, каким образом должен быть представлен тип, который у нас есть. Для строк нет богатого набора опций (строка представлена ​​как есть), но для таких типов, как int s, вы можете иметь разные презентации.

Я действительно думаю, что type, вероятно, является запутанным именем, чтобы дать этот спецификатор.

Ответ 3

Из документации Форматирование строки Python:

Вместо поля field_name следует поле преобразования, которому предшествует восклицательный знак '!' и format_spec, которому предшествует двоеточие ':'.

Нет, это не то же самое.

Например:

Если вы хотите напечатать float как строку, вам потребуется преобразование (float → string).

"{!s}".format(2.1457)
>>> 2.1457
type("{!s}".format(2.1457))
>>> <type 'str'>

Если вы не используете знак перехода, вы получите сообщение об ошибке.

"{:s}".format(2.1457)
>>> ValueError: Unknown format code 's' for object of type 'float'