【问题标题】:Using !s vs. :s to format a string in Python使用 !s 与 :s 在 Python 中格式化字符串
【发布时间】:2017-05-28 14:18:41
【问题描述】:

我真的很好奇 Python 3 中的 :s 格式字符串。The documentation!sconversion 并且 :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

这里有什么问题吗?

【问题讨论】:

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


    【解决方案1】:

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

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

    我的大胆强调。

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

    当您的对象本身不是字符串并且不支持其他格式(并非所有类型都支持)或格式与@987654343不同时,请使用!s(或!a!r) @、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__方法的责任;最后一行不应用 &gt;50s 格式化规范中的对齐操作,Foo.__format__ 方法仅将其用作格式化操作中的文字文本(此处使用 !r 转换)。

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

    【讨论】:

      【解决方案2】:

      不幸的是,您使用字符串作为要格式化的值。使用几乎任何其他对象,您都会发现它们的不同之处。

      用(尽可能)外行的话:

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

      不过,我确实认为,type 给这个说明符起一个令人困惑的名字。

      【讨论】:

        【解决方案3】:

        来自文档,Python String Formatting

        field_name 后跟一个可选的转换字段,前面有一个感叹号'!',和一个格式规范,前面有一个冒号':'。

        所以不,不一样。

        例如:

        如果要将浮点数打印为字符串,则需要进行转换(浮点数→字符串)。

        "{!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'
        

        【讨论】:

        • “转化领域”不言而喻。
        • "..".format(..) 始终是一个字符串。在这种情况下,您的 type() 演示毫无意义,因为它总是相同,无论已对格式化对象应用了何种格式规范或转换。
        • 此外,还有其他格式规范类型会引发异常,即使您应用了!s 转换,例如i
        猜你喜欢
        • 2011-03-24
        • 1970-01-01
        • 2020-03-10
        • 1970-01-01
        • 2011-05-16
        • 1970-01-01
        • 2022-04-08
        • 1970-01-01
        • 2011-06-26
        相关资源
        最近更新 更多