10+ simple examples to use Python string format in detail

In this tutorial we will learn about different string formatting technique available in Python

  • old method i.e. percent(%) formatting (supported in Python 2 and 3)
  • new method i.e. string.format() (Python 2.6 and up)
  • latest method i.e. f-strings - formatted string literal (Python 3.6 and up)

 

Percent % formatting

An old, deprecated way of formatting strings, which you might end up seeing in old code, is the C language style % formatting. In this method, you use the % operator to pass in values. Inside the string, you use the % character, followed by a format specifier, to declare how the value should be inserted;

 

Example-1: Substitute values using % formatting

In this example we will perform basic substitution of strings and integer.

#!/usr/bin/env python3

name = 'deepak'
drink = 'coffee'
price = 3
message = 'Hey %s, this %s costs $%d.' % (name, drink, price)

print(message)

Output from this script:

~]# python3 percent-formatting.py
Hey deepak, This coffee costs $3.

Here,

  • That %s inside the string means to interpolate a string %d means replace it with an integer
  • The number of % appearances in the string needs to match the number of data items after the % that follows the string.
  • A single data item such as name goes right after that final %.
  • Multiple data must be grouped into a tuple as we have added name, drink, price inside parenthesis separated by commas

The following table shows the possible formatting of substitution keys.

ConversionMeaning
%dSigned integer decimal
%iSigned integer decimal
%uObsolete — identical to 'd'
%oSigned octal value
%xSigned hexadecimal — lowercase
%XSigned hexadecimal — uppercase
%fFloating point decimal
%eFloting point exponential—lowercase
%EFloating point exponential—uppercase
%gFloating point format—uses lowercase exponential format if exponent is less than -4 or not less than precision, decimal format otherwise
%GFloating point format—uses uppercase exponential format if exponent is less than -4 or not less than precision, decimal format otherwise
%cSingle character
%rString (converts valid Python object using repr())
%sString (converts valid Python object using str())
%%No argument is converted, results in a '%' character

 

Example-2: Add padding and align the content for strings

You can add other values in the format string between the % and the type specifier to designate minimum and maximum widths, alignment, and character filling.

  • An initial '%' character.
  • An optional alignment character: nothing or '+' means right-align, and '-' means left-align.
  • An optional minwidth field width to use.
  • An optional '.' character to separate minwidth and maxchars.
  • An optional maxchars (if conversion type is s) saying how many characters to print from the data value. If the conversion type is f i.e. floating integer, this specifies precision (how many digits to print after the decimal point).

This may sound confusing and all theoretical, so let's use this in our next example:

#!/usr/bin/env python3

name = 'root'
message1 = 'How'
message2 = 'are you?'

## no extra padding
log = "Hey %s, %s %s " % (name, message1, message2)
print(log)

## added extra padding before message1
log = "Hey %s, %10s %s " % (name, message1, message2)
print(log)

## added extra padding before message1 and right aligned
log = "Hey %s, %+10s %s " % (name, message1, message2)
print(log)

## added extra padding before message1 and left aligned
log = "Hey %s, %-10s %s " % (name, message1, message2)
print(log)

## Max 3 characters allowed in message2
log = "Hey %s, %s %.3s " % (name, message1, message2)
print(log)

## min width is 10 and max character allowed is 3 in message2
log = "Hey %s, %s %10.3s " % (name, message1, message2)
print(log)

Output from this script:

~]# python3 string-formatting.py
Hey root, How are you?
Hey root,        How are you?
Hey root,        How are you?
Hey root, How        are you?
Hey root, How are
Hey root, How        are

Here,

  • First print statement is the default output with no additional formatting
  • Second print statement - we have added additional padding whitespace. Since we have not specified + or -, the default padding is in the left side
  • Third print statement - We are using + sign to align the text in the right side with a defined padding width to provide respective whitespace so the output is similar to second print statement
  • Fourth print statement -  We are using - sign to align the text in the left side with a defined padding width to provide respective whitespace so this time message1 is aligned in the left with additional space in the right side.
  • Fifth print statement - We have defined a character limit in message2 where . (dot) acts as a separator. So only first 3 letters of message 2 is printed. Since I have not defined any padding so the texts are printed with default padding
  • Sixth print statement - I have combined the character limit with minimum width (width.char limit) so now we see that message2 contains additional whitespace padding in the left

 

Example-3: Add extra whitespace and alignment changes using float numbers

Now we will repeat the same exercise we did with strings in the previous example, the only difference is here we take floating number and different message to log.

#!/usr/bin/env python3

name = 'root'
float_num = 95.2

## no extra padding
log = "Hey %s, the number is: %f. Cheers!" % (name, float_num)
print(log)

## added extra padding before float_num
log = "Hey %s, the number is: %10f. Cheers!" % (name, float_num)
print(log)

## ads a + sign to float_num. No whitespace added
log = "Hey %s, the number is: %+10f. Cheers!" % (name, float_num)
print(log)

## added extra padding after float_num in the right side as the text is left aligned
log = "Hey %s, the number is: %-10f. Cheers!" % (name, float_num)
print(log)

## Max 3 numbers allowed in float_num
log = "Hey %s, the number is: %.3f. Cheers!" % (name, float_num)
print(log)

## min width is 10 before float_num and max character allowed is 3 in float_num
log = "Hey %s, the number is: %10.3f. Cheers!" % (name, float_num)
print(log)

Output from this script:

 ~]# python3 string-formatting.py
Hey root, the number is: 95.200000. Cheers!
Hey root, the number is:  95.200000. Cheers!
Hey root, the number is: +95.200000. Cheers!
Hey root, the number is: 95.200000 . Cheers!
Hey root, the number is: 95.200. Cheers!
Hey root, the number is:     95.200. Cheers!

I have added comments with each print statement that should be self explanatory. The output seems different compared to what we had with strings.

 

String formatting using string.format()

  • Python 3.x uses a different formatting system, which is more powerful than the system that Python 2.x uses.
  • The print statement is now a function.
  • Format strings use the curly brackets "{}" to create the replacement fields.
  • Anything that is not contained within the brackets will be considered a literal and no conversation will be done on it.
  • If you have the need to include curly brackets as a literal, you can escape it by using '{{' and '}}.'
  • This formatting system has been backported to Python 2.6 and Python 2.7.

The basic default format string is like this:

#!/usr/bin/env python3

name = 'deepak'
num = 4359

print('Hello {}, your roll number is {}'.format(name, num))

Output from this script:

~]# python3 positional-arg.py
Hello deepak, your roll number is 4359

Here {} considers the order in which .format() function provides the placeholders. If we change the order of .format() values:

#!/usr/bin/env python3

name = 'deepak'
num = 4359

print('Hello {}, your roll number is {}'.format(num, name))

Output from this script:

~]# python3 positional-arg.py
Hello 4359, your roll number is deepak

So the order of the output also has changed along with the .format() placeholders.

To have more control on how string.format() works, the string formatting supports two different types of placements"

  • Positional arguments: We must specify the index position {index} to perform the format
  • Keyword arguments: Here we will replace key with the value where the value can be accessed with key of parameter inside curly braces {key}

 

Positional Arguments

With positional argument we provide the index position inside the curly brackets {}. These placeholders are replaced by respective values from .format() function based on the index position. Just like Python list, the index value here starts with 0 for the first position.

We will take the existing example where we had changed the order of values inside .format() but this time we will provide the positional argument inside {} so that proper values are placed in the template.

#!/usr/bin/env python3

name = 'deepak'
num = 4359

print('Hello {1}, your roll number is {0}'.format(num, name))

Output from this script:

~]# python3 positional-arg.py
Hello deepak, your roll number is 4359

But if you provide the index position which doesn't exist in the .format() function tuple then you will get IndexError

Traceback (most recent call last):
  File "positional-arg.py", line 6, in 
    print('Hello {2}, your roll number is {0}'.format(num, name))
IndexError: tuple index out of range

 

Keyword Arguments

A keyword argument is a name-value pair that you pass to a template. You directly associate the name and the value within the argument, so when you pass the argument to the template, there’s no confusion. Keyword arguments free you from having to worry about correctly ordering your arguments in the message template, and they clarify the role of each value in the print statement or template.

In this example I have used {name} and {num} as the keyword placement and these arguments are defined in .format() function for the replacement

#!/usr/bin/env python3

print('Hello {name}, your roll number is {num}'.format(name='deepak', num=4395))

Output from this script:

~]# python3 keyword-arg.py
Hello deepak, your roll number is 4395

But if you refer to a key which is not defined then you will get KeyError. In this example I have replaced num with test which is not defined and hence we get KeyError.

Traceback (most recent call last):
  File "keyword-arg.py", line 3, in 
    print('Hello {name}, your roll number is {test}'.format(name='deepak', num=4395))
KeyError: 'test'

 

Advanced formatting with string.format()

Similar to % formatting we can achieve more specific layouts by adding extra syntax in the format string. For the formatting method, we use a colon after the possibly empty substitution target’s identification, followed by a format specifier that can name the field size, justification, and a specific type code.

Here’s the formal structure of what can appear as a substitution target in a format string—its four parts are all optional, and must appear without intervening spaces:

{fieldname component !conversionflag :formatspec}

In this substitution target syntax:

  • fieldname is an optional number or keyword identifying an argument
  • component is a string of zero or more “.name” or “[index]” references used to fetch attributes and indexed values of the argument, which may be omitted to use the whole argument value.
  • conversionflag starts with a ! if present, which is followed by r, s, or a to call repr, str, or ascii built-in functions on the value, respectively.
  • formatspec starts with a : if present, which is followed by text that specifies how the value should be presented, including details such as field width, alignment, padding, decimal precision, and so on, and ends with an optional data type code.

Following are some of the format Specifiers using examples

SpecifierDescription
:<20Left Align to a width of 20
:>20Right Align to a width of 20
:^20Center Align to a width of 20
:06.2fZero pad with precision for floating point number
:*>10Asterisk pad right align to a width of 10
:=10Padding is placed after the sign, if any but before digits. ONLY works for numeric types
:+20Force a sign before the number left padded to a width of 20
:−20Force a sign before negative numbers only, left padded to a width of 20
: 20Force a leading space on positive numbers or “-“ on negative numbers, left padded to a width of 20
:,Force thousands comma for numeric
:.2%Expresses percentage (.975 results in 97.50%)
:%M/%d/%YType specific usage. In this case datetime
0:#xFormats an integer as a hex value 0xhh
0:#oFormats an integer as an octal value 0oxx
0:#bFormats an integer as a binary value 0bxxxxxx

 

Example-1: Add extra whitespace padding to strings and integers using string.format()

We will use the advanced formatting syntax to add additional whitespace and padding to strings and integers in this python script:
10+ simple examples to use Python string format in detail

Output from this script:

 ~]# python3 string-format-1.py
Hello deepak, your roll number is 43578. Best of Luck
Hello     deepak, your roll number is      43578. Best of Luck
Hello   deepak  , your roll number is   43578   . Best of Luck
Hello deepak    , your roll number is 43578     . Best of Luck
Hello deepak, your roll number is     +43578. Best of Luck
Hello deepak, your roll number is      43578. Best of Luck

You can check the comments for individual print statement which explains the output.

 

Example-2: Advanced formatting with floating numbers

In this example I have used string and floating point number. We are adding different types of alignment and formatting in each print statement.

#!/usr/bin/env python3

name = 'deepak'
num = 97.65

## no additional formatting
print('Hello {0}, you got {1} marks'.format(name, num))

## add width of 10 characters for both placeholders
print('Hello {0:10}, you got {1:10} marks'.format(name, num))

## Right align to the width of 10
print('Hello {0:>10}, you got {1:>10} marks'.format(name, num))

## Center align to the width of 10
print('Hello {0:^10}, you got {1:^10} marks'.format(name, num))

## Left align to the width of 10
print('Hello {0:<10}, you got {1:<10} marks'.format(name, num))

## Assigned a floating point format to num
print('Hello {0}, you got {1:f} marks'.format(name, num))

## truncating the floating point number to two characters after decimal for num
print('Hello {0:s}, you got {1:.2f} marks'.format(name, num))

## adds a field with a width of six characters and zero padding on the left for num
print('Hello {0:s}, you got {1:06.2f} marks'.format(name, num))

Output from this script:

 ~]# python3 string-format-2.py
Hello deepak, you got 97.65 marks
Hello deepak    , you got      97.65 marks
Hello     deepak, you got      97.65 marks
Hello   deepak  , you got   97.65    marks
Hello deepak    , you got 97.65      marks
Hello deepak, you got 97.650000 marks
Hello deepak, you got 97.65 marks
Hello deepak, you got 097.65 marks

 

Using f-strings for string formatting

f-strings appeared in Python 3.6, and are now the recommended way of formatting strings.

To make an f-string:

  • Type the letter f or F directly before the initial quote.
  • Include variable names or expressions within curly brackets ({}) to get their values into the string.

It’s like the previous section’s “new-style” formatting, but without the format() function, and without empty brackets ({}) or positional ones ({1}) in the format string.

This is a simple example where we are using keyword arguments instead the keywords are defined as variable:

#!/usr/bin/env python3

name = 'deepak'
num = 12345

print(f'Hello {name}, Your roll number is {num}')

Output from this script:

 ~]# python3 f-string-ex.py
Hello deepak, Your roll number is 12345

Formatting with f-strings is shorter than using C-style format strings with the % operator and the str.format method in all cases

 

Example-1: Add additional padding and alignment using f-strings

We can use similar syntax as we used with string.format() to add additional alignment and padding using f-strings:

#!/usr/bin/env python3

name = 'deepak'
num = 12345

## default output without any additional formatting
print(f'Hello {name}, Your roll number is {num}')

## add width of 10 characters for both placeholders
print(f'Hello {name:10}, Your roll number is {num:10}')

## Right align to the width of 10
print(f'Hello {name:>10}, Your roll number is {num:>10}')

## Center align to the width of 10
print(f'Hello {name:^10}, Your roll number is {num:^10}')

## Left align to the width of 10
print(f'Hello {name:<10}, Your roll number is {num:<10}') 

## Add asterisk to the integer and right align the content to total 10 char 
print(f'Hello {name}, Your roll number is {num:*>10}')

## Add zeroes to the integer and right align the content to total 10 char
print(f'Hello {name}, Your roll number is {num:0>10}')

Output from this script:

~]# python3 f-string-ex.py
Hello deepak, Your roll number is 12345
Hello deepak    , Your roll number is      12345
Hello     deepak, Your roll number is      12345
Hello   deepak  , Your roll number is   12345
Hello deepak    , Your roll number is 12345
Hello deepak, Your roll number is *****12345
Hello deepak    , Your roll number is 0000012345

 

Conclusion

In this tutorial, we took an in-depth tour of the string object type. We learned about coding string literals, and we explored string operations, including sequence expressions, string method calls, and string formatting with both expressions and method calls. We also now know that f-strings are succinct yet powerful because they allow for arbitrary Python expressions to be directly embedded within format specifiers.

Leave a Comment

Please use shortcodes <pre class=comments>your code</pre> for syntax highlighting when adding code.