Python string format: When to use !s conversion flag

心不动则不痛 提交于 2019-11-29 05:58:59

It is mentioned in the documentation:

The conversion field causes a type coercion before formatting. Normally, the job of formatting a value is done by the __format__() method of the value itself. However, in some cases it is desirable to force a type to be formatted as a string, overriding its own definition of formatting. By converting the value to a string before calling __format__(), the normal formatting logic is bypassed.

Two conversion flags are currently supported: '!s' which calls str() on the value, and '!r' which calls repr().

An example can be taken (again from the documentation) to show the difference:

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

Simply said:

  • '{0}'.format(a) will use the result of a.__format__() to display the value
  • '{0!s}'.format(a) will use the result of a.__str__() to display the value
  • '{0!r}'.format(a) will use the result of a.__repr__() to display the value

>>> 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

Concerning the second argument of __format__, to quote PEP 3101 "Controlling Formatting on a Per-Type Basis":

The 'format_spec' argument will be either a string object or a unicode object, depending on the type of the original format string. The __format__ method should test the type of the specifiers parameter to determine whether to return a string or unicode object. It is the responsibility of the __format__ method to return an object of the proper type.

Thanks to the comment & answer from @hjpotter92 for explanation:

Here's an example that shows the difference (it's when you override the __format__ method)

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>'
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!