使用!s vs.:s来格式化Python中的字符串

时间:2017-01-13 08:56:22

标签: python string python-3.x string-formatting

我真的很好奇Python 3中的:s格式字符串。The documentation!s转换:s是{{ 1}}。

它还说format_spec将适用!s,但它没有说明与str()类似的内容。我认为它们之间没有显着差异,但我想确定。任何人都可以澄清这些吗?

一些代码示例:

:s

它仍然令人困惑,但让我用我自己的(layperson)的话来结束。

  1. print("{!s}".format("this")) print("{:s}".format("that")) # I want to be sure that these two are processed identically internally 始终为type("whatever".format)
  2. 如果要在格式化之前将对象转换为str,请使用!s
  3. str表示在某些内部格式化过程中,对象(或转换后的对象)将被视为:s。这是默认的str
  4. 这里有什么问题吗?

3 个答案:

答案 0 :(得分:33)

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

  

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

大胆强调我的。

:s仅适用于转换结果(如果未应用转换,则仅适用于原始对象),且仅当对象类型的__format__方法支持该格式化选项时才适用。通常,只有str类型的对象支持此格式化程序;它是默认值,主要是因为Format Specification Mini-Language允许存在类型字符,并且因为较早的% printf-style formatting具有%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个字符宽的字段中右对齐,在左侧填充空格。

答案 1 :(得分:2)

你不幸的是你使用字符串作为要格式化的值。使用几乎任何其他对象,你会得到这些不一样的东西。

(尽我所能)外行人的条款:

  • 转换标志的缺失或存在指定我们要格式化的值的类型,并且按范围,我们将调用谁__format__。正如Martjin指出的那样,通过使用它,我们可以绕过某些行为并更一般地处理该值(如字符串)。它有三种不同的风格,对应于一个对象可以选择将自己表示为字符串的三种不同方式。
  • 类型说明符与其他说明符一起指定最终应如何呈现我们的类型。对于字符串,没有丰富的选项集(字符串按原样显示),但是对于像int这样的类型,您可以使用不同的演示文稿。

我确实认为,type可能是一个令人困惑的名称,无法给出这个说明符。

答案 2 :(得分:-1)

从文档 Python String Formatting

  

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'