click
click

Reputation: 2113

Python string format: When to use !s conversion flag

What's the difference between these 2 string format statements in Python:

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

Both have the same output if a is an integer, list or dictionary. Is the first one {0} doing an implicit str() call?

Source

PS: keywords: exclamation / bang "!s" formatting

Upvotes: 25

Views: 11507

Answers (3)

Sylvain Leroux
Sylvain Leroux

Reputation: 52040

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.

Upvotes: 29

click
click

Reputation: 2113

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

Upvotes: 2

hjpotter92
hjpotter92

Reputation: 80649

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"

Upvotes: 37

Related Questions