Format Strings and Numbers in Python: format()
In Python, you can convert numbers and strings to various formats with the built-in function format() or the string method str.format().
Note that f-strings were introduced in Python 3.6 as a more concise way of using str.format(). Please refer to the following article for more information.
The built-in function: format()
Python provides the built-in format() function for formatting strings.
This function takes the original string (str) and number (int or float) to be formatted as its first argument, and the format specification string as its second argument. The function then returns the formatted string.
i = 255
print(format(i, '#04x'))
print(type(format(i, '#04x')))
# 0xff
# <class 'str'>
s = 'abc'
print(format(s, '*^10'))
# ***abc****
Details of the format specification string are described later.
The string method: str.format()
The format() method is available on strings (str).
In the string that calls the format() method, the {} is known as the replacement field, which is substituted with the format() method's argument. The format specification can be written after : in {}.
Here is the equivalent code using the format() method, corresponding to the above example with the built-in format() function.
print('{:#04x}'.format(i))
print(type('{:#04x}'.format(i)))
# 0xff
# <class 'str'>
print('{:*^10}'.format(s))
# ***abc****
Specify arguments for the replacement field {}
Positional arguments
A string may contain multiple replacement fields. By default, the arguments of format() are inserted in the order they are given.
print('{}-{}-{}'.format(255, 'abc', 1.23))
# 255-abc-1.23
If the number of {} is small, the extra arguments are ignored; if the number of {} is large (not enough arguments), an error will be raised.
print('{}-{}'.format(255, 'abc', 1.23))
# 255-abc
# print('{}-{}-{}-{}'.format(255, 'abc', 1.23))
# IndexError: Replacement index 3 out of range for positional args tuple
The numeric index
You can specify the numeric index in {}, like {0} or {1}. They are replaced by the corresponding arguments.
The same number can be used more than once.
print('{0}-{1}-{0}'.format(255, 'abc'))
# 255-abc-255
Keyword arguments
You can also specify any name within {} and provide it as a keyword argument to format().
print('{name} is {age} years old.'.format(name='Alice', age=20))
# Alice is 20 years old.
Specify list or dictionary
You can also use lists and dictionaries as arguments to format().
To specify the index of the list or the key of the dictionary in the replacement field, use []. Make sure not to use ' or " when specifying dictionary keys.
l = ['one', 'two', 'three']
print('{0[0]}-{0[1]}-{0[2]}'.format(l))
# one-two-three
d1 = {'name': 'Alice', 'age': 20}
d2 = {'name': 'Bob', 'age': 30}
print('{0[name]} is {0[age]} years old.\n{1[name]} is {1[age]} years old.'.format(d1, d2))
# Alice is 20 years old.
# Bob is 30 years old.
A list can be expanded into positional arguments using *, and a dictionary into keyword arguments using **.
l = ['one', 'two', 'three']
print('{}-{}-{}'.format(*l))
# one-two-three
d = {'name': 'Alice', 'age': 20}
print('{name} is {age} years old.'.format(**d))
# Alice is 20 years old.
Braces (curly brackets) {}
If you want to include braces { and } in a string that calls format(), use double braces like {{ and }}. Note that the backslash \ cannot be used for this purpose.
print('{{}}-{num}-{{{num}}}'.format(num=100))
# {}-100-{100}
Format specifications
To specify the format, write the format specification string within {}, separated by a colon :. Details of format specifications are described next.
print('{num} = {num:#x} = {num:#b}'.format(num=255))
# 255 = 0xff = 0b11111111
Examples of format specification string in format()
Both the built-in format() function and the str.format() method use a format specification string to specify the desired format.
This section will illustrate some examples. The sample code uses the str.format() method, but the same applies to the built-in format() function.
Left-align, center, right-align: <, ^, >, =
You can use <, ^, or > to left-align, center, or right-align your text, respectively. Specify the total number of characters.
print('left : {:<10}'.format(100))
print('center: {:^10}'.format(100))
print('right : {:>10}'.format(100))
# left : 100
# center: 100
# right : 100
You can specify the padding character. If omitted, as in the example above, it is filled with spaces.
print('left : {:*<10}'.format(100))
print('center: {:*^10}'.format(100))
print('right : {:*>10}'.format(100))
# left : 100*******
# center: ***100****
# right : *******100
> does not consider signs (-, +).
When = is used instead of >, the sign is placed first and then filled with the specified character. Details related to the sign are described below.
print('sign: {:0>10}'.format(-100))
print('sign: {:0=10}'.format(-100))
# sign: 000000-100
# sign: -000000100
While <, ^, and > can be used with strings, an error is raised if = is used. To apply = to a string, you must first convert the string to a number with int() or float().
# print('sign: {:0=10}'.format('-100'))
# ValueError: '=' alignment not allowed in string format specifier
print('sign: {:0=10}'.format(int('-100')))
# sign: -000000100
There are also ljust(), center(), and rjust() methods provided. For more information, see the following article.
Zero-padding
By specifying 0 as the padding character and omitting the alignment option (<, ^, >), it is treated as if = is specified.
print('zero padding: {:0=10}'.format(100))
print('zero padding: {:010}'.format(100))
# zero padding: 0000000100
# zero padding: 0000000100
print('zero padding: {:0=10}'.format(-100))
print('zero padding: {:010}'.format(-100))
# zero padding: -000000100
# zero padding: -000000100
Since it is considered =, an error is raised if a string is specified as an argument, as described above.
# print('zero padding: {:010}'.format('-100'))
# ValueError: '=' alignment not allowed in string format specifier
The zfill() method is also provided for zero-padding. See the following article for more details.
Leading sign prefix: +, space
By default, only negative numbers are prefixed with a sign -.
However, by using + in the format string, positive numbers are prefixed with +. By using space in the format string, positive numbers are prefixed with a space.
print('sign: {}'.format(100))
print('sign: {}'.format(-100))
# sign: 100
# sign: -100
print('sign: {:+}'.format(100))
print('sign: {:+}'.format(-100))
# sign: +100
# sign: -100
print('sign: {: }'.format(100))
print('sign: {: }'.format(-100))
# sign: 100
# sign: -100
Note that, by default, the positive number is padded with an additional character when padding.
print('sign: {:06}'.format(100))
print('sign: {:06}'.format(-100))
# sign: 000100
# sign: -00100
print('sign: {:+06}'.format(100))
print('sign: {:+06}'.format(-100))
# sign: +00100
# sign: -00100
print('sign: {: 06}'.format(100))
print('sign: {: 06}'.format(-100))
# sign: 00100
# sign: -00100
The sign option should be written after the alignment option.
print('sign: {:*>6}'.format(100))
print('sign: {:*>6}'.format(-100))
# sign: ***100
# sign: **-100
print('sign: {:*>+6}'.format(100))
print('sign: {:*>+6}'.format(-100))
# sign: **+100
# sign: **-100
print('sign: {:*> 6}'.format(100))
print('sign: {:*> 6}'.format(-100))
# sign: ** 100
# sign: **-100
Separator: ,, _
A comma , or an underscore _ can be used as a thousands separator. Note that the underscore option was added in Python 3.6.
print('{:,}'.format(100000000))
print('{:_}'.format(100000000))
# 100,000,000
# 100_000_000
For float, only the integer part is separated.
print('{:,}'.format(1234.56789))
print('{:_}'.format(1234.56789))
# 1,234.56789
# 1_234.56789
Binary, octal, hexadecimal: b, o, x, X
You can format integers to binary, octal, and hexadecimal representations.
b: binaryo: octalx: hexadecimal (lowercase)X: hexadecimal (uppercase)
print('bin: {:b}'.format(255))
print('oct: {:o}'.format(255))
print('hex: {:x}'.format(255))
print('HEX: {:X}'.format(255))
# bin: 11111111
# oct: 377
# hex: ff
# HEX: FF
It is possible to use zero-padding for alignment when dealing with binary or hexadecimal notation.
print('bin: {:08b}'.format(255))
print('oct: {:08o}'.format(255))
print('hex: {:08x}'.format(255))
print('HEX: {:08X}'.format(255))
# bin: 11111111
# oct: 00000377
# hex: 000000ff
# HEX: 000000FF
Prefixes like 0b or 0x can be added with #. Be aware that these prefixes are also accounted for when using zero-padding.
print('bin: {:#b}'.format(255))
print('oct: {:#o}'.format(255))
print('hex: {:#x}'.format(255))
print('HEX: {:#X}'.format(255))
# bin: 0b11111111
# oct: 0o377
# hex: 0xff
# HEX: 0XFF
print('bin: {:#010b}'.format(255))
print('oct: {:#010o}'.format(255))
print('hex: {:#010x}'.format(255))
print('HEX: {:#010X}'.format(255))
# bin: 0b11111111
# oct: 0o00000377
# hex: 0x000000ff
# HEX: 0X000000FF
Only the underscore _ can be used as a separator in binary, octal, and hexadecimal representations. Underscores are inserted every 4 digits.
print('hex: {:08x}'.format(255))
print('hex: {:09_x}'.format(255))
print('hex: {:#011_x}'.format(255))
# hex: 000000ff
# hex: 0000_00ff
# hex: 0x0000_00ff
Only integers (int) can be formatted to binary, octal, or hexadecimal. If you want to format a numeric string, use int() to convert it to an integer.
# print('hex: {:08x}'.format('255'))
# ValueError: Unknown format code 'X' for object of type 'str'
print('hex: {:08x}'.format(int('255')))
# hex: 000000ff
For more information on binary, octal, and hexadecimal representation in Python, see the following article.
Fixed-point notation: f, F
Automatic conversion of float to str can result in scientific notation depending on the value. If you use f in your format specification string, it will ensure the conversion to fixed-point notation.
print('{}'.format(0.00001234))
print('{}'.format(12340000000000000.0))
print('{:f}'.format(0.00001234))
print('{:f}'.format(12340000000000000.0))
# 1.234e-05
# 1.234e+16
# 0.000012
# 12340000000000000.000000
If you prefer scientific notation consistently, use e or E as detailed below.
As demonstrated above, six decimal places are used by default. To specify the number of decimal places (precision), use .[number of digits]f.
print('{:.2f}'.format(123.456))
print('{:.5f}'.format(123.456))
print('{:.3f}'.format(0.0001234))
# 123.46
# 123.45600
# 0.000
If the resulting value has fewer digits than the original, the value is rounded. Note that this rounding adheres to the rules of even-number rounding. For example, 0.5 is rounded down to 0.
print('{:.0f}'.format(0.4))
print('{:.0f}'.format(0.5))
print('{:.0f}'.format(0.6))
# 0
# 0
# 1
You can use the quantize() method of the standard library decimal for standard rounding (rounding half up). See the following article.
Values that exceed the maximum possible value for a float are automatically treated as infinity, inf. If F is used, the output will be in uppercase: INF. In such cases, nan is also uppercase: NAN.
print('{:.5f}'.format(10e1000))
print('{:.5F}'.format(10e1000))
# inf
# INF
Scientific notation: e, E
By specifying e or E in your format string, you ensure the value is always converted to scientific notation. If e is specified, the output will also be lowercase e; if E is specified, the output will be uppercase E.
print('{:e}'.format(0.0001234))
print('{:E}'.format(0.0001234))
# 1.234000e-04
# 1.234000E-04
As with f and F, you can specify the number of digits following the decimal point. The integer part is one digit, and the decimal point is followed by the specified number of digits.
print('{:.5e}'.format(0.0001234))
print('{:.2e}'.format(0.0001234))
# 1.23400e-04
# 1.23e-04
print('{:.5e}'.format(987.65))
print('{:.2e}'.format(987.65))
# 9.87650e+02
# 9.88e+02
Note that e, E, +, and - are also taken into account when aligning the output.
print('{:>12.5e}'.format(987.65))
print('{:012.2e}'.format(987.65))
# 9.87650e+02
# 00009.88e+02
General format: g, G
g means "general format" and automatically switches between fixed-point and scientific notation depending on the value.
print('{:g}'.format(0.0001234))
print('{:g}'.format(0.00001234))
# 0.0001234
# 1.234e-05
You can specify significant digits using .[number of digits]g. Note that this does not specify the number of decimal places.
The output may be converted to scientific notation.
print('{:.2g}'.format(123.456))
print('{:.3g}'.format(123.456))
print('{:.8g}'.format(123.456))
print('{:.3g}'.format(0.0001234))
# 1.2e+02
# 123
# 123.456
# 0.000123
As shown above, trailing zeros after the decimal point are omitted by default. If you add #, these zeros won't be omitted. This also adds a trailing decimal point to integers.
print('{:#.2g}'.format(123.456))
print('{:#.3g}'.format(123.456))
print('{:#.8g}'.format(123.456))
print('{:#.3g}'.format(0.0001234))
# 1.2e+02
# 123.
# 123.45600
# 0.000123
Omitting g gives the same result in most cases, but not when dealing with integer output.
print('{:.2}'.format(123.456))
print('{:.3}'.format(123.456))
print('{:.8}'.format(123.456))
print('{:.3}'.format(0.0001234))
# 1.2e+02
# 1.23e+02
# 123.456
# 0.000123
print('{:#.2}'.format(123.456))
print('{:#.3}'.format(123.456))
print('{:#.8}'.format(123.456))
print('{:#.3}'.format(0.0001234))
# 1.2e+02
# 1.23e+02
# 123.45600
# 0.000123
If you compare the same value formatted with f, e, g, and the default, the results will look like this:
print('{:.3f}'.format(123.456))
print('{:.3e}'.format(123.456))
print('{:.3g}'.format(123.456))
print('{:.3}'.format(123.456))
# 123.456
# 1.235e+02
# 123
# 1.23e+02
print('{:.8f}'.format(123.456))
print('{:.8e}'.format(123.456))
print('{:.8g}'.format(123.456))
print('{:.8}'.format(123.456))
# 123.45600000
# 1.23456000e+02
# 123.456
# 123.456
If you want to display a wide range of values with fixed width, use the exponential notation of e or E.
print('{:.4e}'.format(123.456))
print('{:.4e}'.format(0.000012345))
print('{:.4e}'.format(12))
# 1.2346e+02
# 1.2345e-05
# 1.2000e+01
Remember, using G instead of g capitalizes letters, as in E, INF, or NAN.
print('{:.2g}'.format(123.456))
print('{:.2g}'.format(10e1000))
print('{:.2G}'.format(123.456))
print('{:.2G}'.format(10e1000))
# 1.2e+02
# inf
# 1.2E+02
# INF
Percentage: %
By specifying % in your format string, the value is multiplied by 100 and expressed as a percentage. Like with f, you can specify the number of decimal places. Six decimal places are used by default.
Left-justified, centered, right-justified, and zero-filled alignments are also available. The % symbol is also counted as a character.
print('{:%}'.format(0.12345))
print('{:.2%}'.format(0.12345))
# 12.345000%
# 12.35%
print('{:%}'.format(10))
print('{:.2%}'.format(10))
# 1000.000000%
# 1000.00%
print('{:>10.2%}'.format(0.12345))
print('{:010.2%}'.format(0.12345))
# 12.35%
# 000012.35%
Date and time (datetime)
You can also use the format codes for the datetime, date, and time objects from the datetime module in the format string.
import datetime
dt = datetime.datetime(2020, 1, 5, 20, 15, 30)
print('datetime: {}'.format(dt))
# datetime: 2020-01-05 20:15:30
print('datetime: {:%A, %m/%d/%Y %I:%M:%S %p}'.format(dt))
# datetime: Sunday, 01/05/2020 08:15:30 PM
print('datetime: {}'.format(dt.isoformat()))
# datetime: 2020-01-05T20:15:30
As shown in the final example, using the isoformat() method can be more convenient when you want to convert to the ISO 8601 format than specifying individual format codes.