使用!s与:s在Python中格式化字符串

问题描述

我对Python3中的:s格式字符串非常好奇。The documentation说!s!s转换,:sformat_spec

它还说!s将应用str(),但它没有说任何关于:s的类似内容。我认为它们之间没有显著差异,但我想确定一下。有人能澄清这些吗?

一些代码示例:

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

这仍然令人困惑,但让我用我自己(外行)的话来总结一下。

  1. type("whatever".format)始终为str
  2. 如果要在格式化前将对象转换为str,请使用!s
  3. :s表示对象(或转换后的对象)在某个内部格式化过程中将被视为str。默认设置format_spec

这里有什么问题吗?


解决方案

!s,其兄弟!a!r在前分别应用str()ascii()repr()。这些被称为转换标志,是Format String Syntax spec的一部分,而不是per-field formatting spec在插入时应用于值:

转换字段在格式化前导致类型强制。通常,格式化值的工作由值本身的__format__()方法完成。但是,在某些情况下,需要强制将类型格式化为字符串,从而覆盖其自身的格式设置定义。通过在调用__format__()之前将值转换为字符串,可以绕过正常的格式设置逻辑。

强调我的。

仅当该对象类型的__format__方法支持该格式选项时,

:s才应用于转换结果(如果未应用转换,则应用于原始对象)。通常,只有str类型的对象支持该格式化程序;它是默认的,主要是因为Format Specification Mini-Language允许类型字符的存在,而且较旧的% printf-style formatting具有%s格式。如果尝试将s类型应用于不支持该类型的对象,则会出现异常。

如果对象本身不是字符串,并且不支持其他格式(并非所有类型都支持),或者格式与其str()ascii()repr()转换不同,请使用!s(或!a!r):

>>> 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 xe5xe9xe6 some non-ASCII>
No conversions: Foo formatted to '>50s' spec

注意:格式规范指定的所有格式由__format__方法负责;>50s格式规范中的最后一行不应用对齐操作,Foo.__format__方法仅将其用作格式操作中的文字文本(此处使用!r转换)。

另一方面,对于转换值,使用str.__format__方法,输出在50个字符宽度的字段中右对齐,左侧用空格填充。

相关文章