!s, and its brethren !a and !r apply str(), ascii() and repr() respectively before interpolation and formatting. These are called conversion flags, and are part of the Format String Syntax spec, not the per-field formatting spec applied to values when interpolating:
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.
Bold emphasis mine.
:s only applies afterwards to the conversion result (or the original object if no conversion had been applied), and only if the __format__ method for the type of object supports that formatting option. Usually, only objects of type str support this formatter; it's there as the default, mostly because the Format Specification Mini-Language allows for the existence of a type character and because the older % printf-style formatting had a %s format. If you tried to apply the s type to an object that doesn't support it, you'd get an exception.
Use !s (or !a or !r) when you have an object that is not itself a string and either doesn't support formatting otherwise (not all types do) or would format differently from their str(), ascii() or repr() conversions:
>>> 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
Note: all formatting specified by the format spec are the responsibility of the __format__ method; the last line does not apply the alignment operation in the >50s formatting spec, the Foo.__format__ method only used it as literal text in a formatting operation (using a !r conversion here).
For the converted values, on the other hand, the str.__format__ method is used and the output is aligned to the right in a 50 character wide field, padded with spaces on the left.