Python字符串格式化:何时使用!s转换标志

25 投票
3 回答
10526 浏览
提问于 2025-04-18 18:09

这两种字符串格式化的语句在Python中有什么区别呢:

'{0}'.format(a)
'{0!s}'.format(a)

如果a是一个整数、列表或字典,这两种方式的输出是一样的。第一个{0}是不是在隐式地调用str()呢?

来源

附注:关键词:感叹号 / bang "!s" 格式化

3 个回答

2

感谢@hjpotter92的评论和回答提供的解释:

这里有一个例子,展示了不同之处(这是在你重写__format__方法的时候)

class MyClass:
    i = 12345
    def __format__(self, i):
        return 'I Override'

>>> obj = MyClass()

>>> '{0}'.format(obj)
'I Override'

>>> '{0!s}'.format(obj)
'<__main__.MyClass instance at 0x021AA6C0>'
28

简单来说:

  • '{0}'.format(a) 会使用 a.__format__() 的结果来显示值
  • '{0!s}'.format(a) 会使用 a.__str__() 的结果来显示值
  • '{0!r}'.format(a) 会使用 a.__repr__() 的结果来显示值

>>> class C:
...     def __str__(self): return "str"
...     def __repr__(self): return "repr"
...     def __format__(self, format_spec): return "format as " + str(type(format_spec))
... 
>>> c = C()
>>> print "{0}".format(c)
format as <type 'str'>
>>> print u"{0}".format(c)
format as <type 'unicode'>
>>> print "{0!s}".format(c)
str
>>> print "{0!r}".format(c)
repr

关于 __format__ 的第二个参数,引用 PEP 3101 "按类型控制格式化"

'format_spec' 参数可以是一个字符串对象或一个unicode对象,这取决于原始格式字符串的类型。__format__ 方法应该检查 specifiers 参数的类型,以决定返回字符串还是unicode对象。__format__ 方法有责任返回正确类型的对象。

37

文档中提到:

转换字段会在格式化之前进行类型转换。通常,格式化一个值的工作是由这个值自己的 __format__() 方法来完成的。不过,在某些情况下,我们希望强制将某个类型格式化为字符串,这样就可以覆盖它自己定义的格式化方式。通过在调用 __format__() 之前将值转换为字符串,可以绕过正常的格式化逻辑。

目前支持两种转换标志:'!s' 会对值调用 str(),而 '!r' 则会调用 repr()

可以通过一个例子(同样来自 文档)来展示它们之间的区别:

>>> "repr() shows quotes: {!r}; str() doesn't: {!s}".format('test1', 'test2')
"repr() shows quotes: 'test1'; str() doesn't: test2"

撰写回答