Python format(): Learn the Syntax Step by Step

The Chinese version of this article: Python format() 语法详解

Basic Usage

print("Hello I am {} and he is {}!".format('Tom','Jerry'))

# Output:Hello I am Tom and he is Jerry!

You can put a "{}" inside a string, and then it will be replaced by the values passed into the str.format() method. The bracket and characters within them are called format fields.

Positional Arguments

We can also put a number in the "{}" to refer to the position of values passed into the str.format() method. These are called positional arguments.

print("Hello I am {1} and he is {0}!".format('Tom','Jerry'))

# Output:Hello I am Jerry and he is Tom!

Keyword Arguments

Using the name of the argument to refer to the values is also possible. These are called keyword arguments.

print("Hello I am {cat} and he is {mouse}!".format(cat='Tom',mouse='Jerry'))

# Output:Hello I am Tom and he is Jerry!

Positional and Keyword Arguments

These two can be arbitrarily combined:

print("Hello I am {0} and he is {mouse}!".format('Tom',mouse='Jerry'))

# Output:Hello I am Tom and he is Jerry!

You can also pass a dictionary to the str.format():

scores = {'Jerry':98, "Tom":99, "Tuffy":100}
height = {'Jerry':1, "Tom":4, "Tuffy":0.5}

print("Tom's score is {0[Tom]}. Tuffy's height is {1[Tuffy]}!".format(scores,height))

# Output:Tom's score is 99. Tuffy's height is 0.5!

The "0" and "1" within the "{}" are referred to as the scores and the height in the format(). Then we use "[]" to access the keys.

Format String Syntax

Format String Grammar from Documentation

After we learn the basics, we can take a deep dive into the str.format() syntax. First, the things inside the braces {} are called replacement fields. Then we have the following syntax:

replacement_field ::=  "{" [field_name] ["!" conversion] [":" format_spec] "}"

( If you don't understand this type of syntax, it is totally fine, I will guide you through the following. If you are curious about the name, it is called Backus–Naur form (BNF) )

The "field_name" here corresponds to the Positional Arguments and Keyword Arguments above.

The "["!" conversion]" tells us that we can make conversions on the arguments. Only three types of conversions are currently supported:

  • !s --> str()
  • !r --> repr()
  • !a --> ascii()

For example:

s = '''Hello
Hey'''

print("{!a}".format(s))

# Output:'Hello\nHey'

Format Specification

Format Specifier General Form from Documentation

The "format_spec" is actually the one you see the most often, like the part after the colon (:) in "{0:2d}".

format_spec's syntax is defined as follows:

format_spec     ::=  [[fill]align][sign][#][0][width][grouping_option][.precision][type]

[sign]

We talk about the [sign] first, sign's syntax is defined as follows:

sign            ::=  "+" | "-" | " "

The options and meaning:

Option Meaning
+ both positive and negative numbers should have a sign
- only negative numbers should have a sign
space add a leading space for positive numbers, and a minus sign for negative numbers

For example:

print("{:+} {:+}".format(3, -3))
print("{:-} {:-}".format(3, -3))
print("{: } {: }".format(3, -3))

Output:

+3 -3
3 -3
 3 -3

[[fill]align]

We then look at the [[fill]align], fill and assign's syntax:

fill            ::=  <any character>
align           ::=  "<" | ">" | "=" | "^"

align's option and meaning:

Option Meaning
< left-aligned
> right-aligned
= Add padding between the sign (if any) and digits. This can be used for printing fields in the form '+000000120'.

This alignment option is only valid for numeric types. It becomes the default for numbers if we add '0'(zero) before the [width].
^ center

For example:

print("{:>10}".format('12345'))
print("{:*^10}".format('12345'))
print("{:*=+10}".format(12345))

Output:

     12345
**12345***
+****12345

[type]

type's syntax:

type            ::=  "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"

The type determines how the data should be presented:

Type Meaning
'd' Decimal
'b' Binary
'o' Octal
'x' Hex

For example:

print("Decimal: {0:d}   Binary: {0:b}   Octal: {0:o}    Hex: {0:x}".format(15))

Output:

Decimal: 15   Binary: 1111   Octal: 17    Hex: f

More types can be referred to as Format String Syntax.

[#]

The '#' option is for "alternate form" conversion. It is only valid for integer, float, and complex types.

For integers, if we are using binary, octal, and hexadecimal output, the respective prefix '0b', '0o','0x', or '0X' will be added.

For example:

print("Decimal: {0:#d}   Binary: {0:#b}   Octal: {0:#o}    Hex: {0:#x}    Hex_Upper: {0:#X}".format(15))

Output:

Decimal: 15   Binary: 0b1111   Octal: 0o17    Hex: 0xf    Hex_Upper: 0XF

For float and complex, it will cause the result to always contain a decimal point:

print("{:.0f} {}".format(3, 3j+1))
print("{:#.0f} {:#}".format(3, 3j+1))

Output:

3 (1+3j)
3. (1.+3.j)

[0]

When no explicit alignment is given, add a '0' before the [width] will pad '0's between sign and number.

This is equivalent to set [[fill]align] with the [fill] being '0' and align being '='.

For example:

print("{:+06}".format(-3))

Output:

+00003

The '6' here is the [width] part.

This is equivalent to:

print("{:0=+6}".format(3))

[grouping_option]

grouping_option's syntax:

grouping_option ::=  "_" | ","

There are only two options for grouping as we see here. One is '',", the other is "_".

The ''," option uses a comma as a thousands separator:

print("{:,}".format(1000000000))

Output:

1,000,000,000

The "_" option uses underscore as a thousands separator for float and decimal.

print("{:_d}".format(1000000000))
print("{:_f}".format(99999.9999))

Output:

1_000_000_000
99_999.999900

For other integer presentation types 'b', 'o', 'x' and 'X', it will be inserted every 4 digits.

For example:

# 2^20 - 1 = 1048575
print("{:_b}".format(1048575)) #Binary
print("{:_o}".format(1048575)) #Octal
print("{:_x}".format(1048575)) #Hexadecimal
print("{:_X}".format(1048575)) #Hexadecimal with Capital Letters

Output:

1111_1111_1111_1111_1111
377_7777
f_ffff
F_FFFF

[.precision]

precision's syntax:

precision       ::=  digit+

I believe that many people use this one when they are searching for answers on Stack Overflow.

It specifies how many digits should be displayed after the decimal point for a floating-point value. If it is used for non-number types, it indicates how many characters will be used.

For example:

print("{:.3f}".format(3.1415926))
print("{:.3}".format("Hello World"))

Output:

3.142
Hel

References

  1. Python Documents: The String format() Method
  2. Python Documents: Format String Syntax

I hope this article helps you!

(Support me by a coffee monthly or becoming a member. 😊😊)