25

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

3 Answers 3

38

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"
Sign up to request clarification or add additional context in comments.

3 Comments

I get the same result whether I use {0} or {0!s} with a string argument to format. How does repr() come into picture?
@click {x} and {x!s} will give the same result for strings and integers. Type coercion occurs if you've a different __format__() and __str__() defined (eg. for some custom class, like a vector or complex number etc.).
You'll almost always get the same result for {} and {!s}, because of this suggestion from the Python docs: A general convention is that an empty format string ("") produces the same result as if you had called str() on the value. All the built-in types I'm aware of follow this convention.
29

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.

Comments

2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.