I'm really curious about :s
format string in Python 3. The documentation says !s
is conversion and that :s
is format_spec
.
It also says !s
will apply str()
, but it doesn't say anything similar about :s
. I think there's no significant difference between them, but I want to be sure. Can anyone clarify these?
Some code example:
print("{!s}".format("this"))
print("{:s}".format("that"))
# I want to be sure that these two are processed identically internally
It's still confusing, but let me wrap up with my own (layperson's) words.
type("whatever".format)
is always str
.!s
if you want convert the object into str
before formatting.:s
means that the object(or the converted object) will be treated as str
during some internal formatting process. It's the default format_spec
.Is anything wrong here?
What is % string formatting in Python? One of the older ways to format strings in Python was to use the % operator. You can create strings and use %s inside that string which acts like a placeholder. Then you can write % followed be the actual string value you want to use.
The % symbol is used in Python with a large variety of data types and configurations. %s specifically is used to perform concatenation of strings together. It allows us to format a value inside a string. It is used to incorporate another string within a string.
PythonServer Side ProgrammingProgramming. The %s specifier converts the object using str(), and %r converts it using repr().
In, Python %s and %d are used for formatting strings. %s acts a placeholder for a string while %d acts as a placeholder for a number. Their associated values are passed in via a tuple using the % operator. This code will print abc 2.
!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.
You're unlucky you used strings as the value to be formatted. Using pretty much any other object you'd get how these aren't the same.
In (as much as I can) layman's terms:
__format__
we'll be calling. As Martjin points out, by using this we can bypass certain behavior and treat the value more generically (like a string). It comes in three different flavors that correspond to the three different ways an object can choose to represent itself as a string.int
s, you can have different presentations.I do think, though, that type
is probably a confusing name to give this specifier.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With