Python String Formatting Examples

Learn about all the facilities available with python string formatting

“The saddest aspect of life right now is that science gathers knowledge faster than society gathers wisdom.” ― Isaac Asimov

 

1. Introduction

String formatting in python is somewhat complicated by the fact that there are a lot of flags and options. Let us learn about them.

You can also check out this article on string formatting in java.

2. Position and Keyword Arguments

A format string is composed of normal characters other than { and } (which are used to enclose the format directives).

print 'hello, {}'.format('joe')
# prints
hello, joe

Each additional pair of {} refers to the next positional argument.

print 'i am a {} and my sound is: {}'.format('dog', 'bark')
# prints
i am a dog and my sound is: bark

Of course you can use an index to specify the positional argument. The index starts from 0 for the first argument.

print 'i am a {1}'.format('dog','cat')
# prints
i am a cat

Using named arguments: Use keyword arguments to specify values for named arguments.

print 'i am a {animal} and i {sound}'.format(animal='dog', sound='bark')
# prints
i am a dog and i bark

You can mix the two, but the positional arguments must come first in the list.

print 'i am a {animal} and i {1}'.format('meow', 'bark', animal='dog', sound='bark')
# prints
i am a dog and i bark

3. Using a Dictionary

Let us look into using a dictionary as an argument. The simplest way is like this:

print 'i am a {0[animal]} and my sound is: {0[sound]}'.format({'animal': 'dog', 'sound': 'bark'})
# prints
i am a dog and my sound is: bark

Here too you can use keyword arguments as follows:

print '6. i am a {animal[type]} and my sound is: {animal[sound]}'.format(animal = {'type': 'dog', 'sound': 'bark'})
# prints
6. i am a dog and my sound is: bark

How about using attribute syntax (dot(.) between names)? First you need add attributes to your dict. You cannot do that for the builtin dict, so do the following.

class MyDict(dict):
    pass

Now you can set attributes and use them. (Merely declaring a subclass of dict allows you to add attributes to it.)

d = MyDict()
d.animal = 'dog'
d.sound = 'bark'
print '7. i am a {0.animal} and my sound is: {0.sound}'.format(d)
# prints
7. i am a dog and my sound is: bark

Here is a hack for accomplishing the same.

Exercise to the reader: Can you explain what is going on here? Please do so in the comments.

e = type('xyz', (dict,), {'animal': 'dog', 'sound': 'bark'})()
print '8. i am a {0.animal} and my sound is: {0.sound}'.format(e)
# prints
8. i am a dog and my sound is: bark

4. Using Array Arguments

The arguments to the format() method are a list of positional arguments. Can you pass an array for the arguments? Let us see what happens.

arr = ['joe', 'jack', 'dan']
print 'hello, {}'.format(arr)
# prints
hello, ['joe', 'jack', 'dan']

The whole array is printed. You can select an element of the array by specifying the index.

print 'hello, {0[1]}'.format(arr)
# prints
hello, jack

To pass the array as positional arguments, you can unpack it with the * operator.

print 'hello, {}'.format(*arr)
# prints
hello, joe

5. Formatting Strings

Now that we have covered various methods of addressing a parameter in the argument list, let us now look into formatting of types. We start with the most common: string formatting.

5.1. Specifying Width

Specify width with the number of characters as follows. (The angle brackets (< and >) are used to show the complete field.

print '1. hello, <{0:30}>'.format('joe')
# prints
1. hello, <joe                           >

String fields are left-justified by default. To right justify:

print '2. hello, <{0:>30}>'.format('joe')
# prints
2. hello, <                           joe>

To center within the field:

print '3. hello, <{0:^30}>'.format('joe')
# prints
3. hello, <             joe              >

The width as specified above applies only as a guide. If the value is larger, no truncation occurs.

print '4. hello, <{0:10}>'.format('I am the terminator')
# prints
4. hello, <I am the terminator>

To truncate the field to a maximum width, begin the width specification with a period (.) (this specification is called the precision).

print '5. hello, <{0:.10}>'.format('I am the terminator')
# prints
5. hello, <I am the t>

Use both width and precision when you want a standard width and truncation.

print '6. i am the <{0:30.8}>\n     not an <{1:30.8}>'.format('terminator', 'avenger')
# prints
6. i am the <terminat                      >
     not an <avenger                       >

5.2. Fill and Justification

Till now, we have see the use of space (” “ or 0x20) as the fill character. Let us now use hypen (0x2d).

Here we have a right-justified field with hypens.

print '7. i am the <{0:->30}>'.format('terminator')
# prints
7. i am the <--------------------terminator>

Using star (0x2A) for centering.

print '8. i am the <{0:*^30}>'.format(' avenger ')
# prints
8. i am the <********** avenger ***********>

Or left-justify using hyphens again.

print '9. i am the <{0:-<30}>'.format(' avenger ')
# prints
9. i am the < avenger --------------------->

6. Formatting Integers

Integers can be formatted in several different ways. First let us look at the default.

print '10. I am <{}> years old and my income is <{}>'.format(39, 40000)
# prints
10. I am <39> years old and my income is <40000>

6.1. Using Commas

We should format the salary using commas. (The format specification must be preceded by colon (:, 0x3A)).

print '11. I am <{}> years old and my income is <{:,}>'.format(39, 40000)
# prints
11. I am <39> years old and my income is <40,000>

6.2. Locale Aware Thousands Separator

Using , (comma) as described above always shows the thousands separator. To use the current locale setting, you should use the n format directive.

With the default (C) locale, you get no thousands separator with the n directive. This is unlike using , which always outputs the thousands separator.

# default (C) locale setting
print 'I am <{}> years old and my income is <{:,}>'.format(39, 40000)
print 'I am <{}> years old and my income is <{:n}>'.format(39, 40000)
# prints
I am <39> years old and my income is <40,000>
I am <39> years old and my income is <40000>

Let us now set the locale to en_US. The thousands separator for this locale is still ,.

import locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
print 'I am <{}> years old and my income is <{:,}>'.format(39, 40000)
print 'I am <{}> years old and my income is <{:n}>'.format(39, 40000)
# prints
I am <39> years old and my income is <40,000>
I am <39> years old and my income is <40,000>

Here is the usage of this facility in a locale with a different thousands separator.

locale.setlocale(locale.LC_ALL, 'es_ES.UTF-8')
print 'I am <{}> years old and my income is <{:,}>'.format(39, 40000)
print 'I am <{}> years old and my income is <{:n}>'.format(39, 40000)
# prints
I am <39> years old and my income is <40,000>
I am <39> years old and my income is <40.000>

6.3. Field Width Allowed But Not Precision

How about using field width? (Precision cannot be specified for integer fields.)

print '12. I am <{:4}> years old and my income is <{:10,}>'.format(39, 40000)
# prints
12. I am <  39> years old and my income is <    40,000>

6.4. Aligning Numbers

Specifying alignment?

  • Use < for left
  • ^ centers output
  • Right (>) is the default for integer fields.
print '13. I am <{:<8}> years old and my income is <{:^20,}>'.format(39, 40000)
# prints
13. I am <39      > years old and my income is <       40,000       >

6.5. Using Fill Characters

Let us use a fill character. Typical application: for accounting purposes where leaving spaces before and after numbers can be an invitation for fraudsters.

print '14. I am <{:->8}> years old and my income is <{:x>20,}>'.format(39, 40000)
# prints
14. I am <------39> years old and my income is <xxxxxxxxxxxxxx40,000>

6.6. Signs and Positive/Negative Numbers

When you need to show a sign before the number, you have three options:

  • use to show a sign only for negative numbers
  • a + shows the correct sign for both positive and negative numbers
  • a space (0x20) shows a space for +ve and a sign for -ve numbers.
print '15. Price of the item is <{}>, Amount due is <{:+}>'.format(299, 399)
print '16. Price of the item is <{:8}>, Amount due is <{:+8}>'.format(299, -99)
# prints
15. Price of the item is <299>, Amount due is <+399>
16. Price of the item is <     299>, Amount due is <     -99>

6.7. Preceding Zeros

Need the number preceded by zeros upto the field width? Use a 0 before the field width.

print '17. Price of the item is <{:08}>, Amount due is <{:+08}>'.format(299, -99)
# prints
17. Price of the item is <00000299>, Amount due is <-0000099>

6.8. Binary, Octal and Hexadecimal Output

Normally the integer is output in base 10. This is equivalent to specifying a format directive d. Alternative directives include:

  • b renders the number in binary (base 2)
  • o outputs octal (base 8)
  • x outputs the numerical value in base 16
  • X outputs in base 16 using uppercase characters for digits above 9.
print '18. The value is {0:d} in base 10, {0:b} in base 2, {0:o} in octal, {0:x} in hex and {0:X} in hex upper'.format(28)
# prints
18. The value is 28 in base 10, 11100 in base 2, 34 in octal, 1c in hex and 1C in hex upper

An option with these outputs is to use # to request alternate output. It has no effect on base 10 output. But for the others output is preceded by a 0.

print '19. The value is {0:#d} in base 10, {0:#b} in base 2, {0:#o} in octal, {0:#x} in hex and {0:#X} in hex upper'.format(28)
# prints
19. The value is 28 in base 10, 0b11100 in base 2, 0o34 in octal, 0x1c in hex and 0X1C in hex upper

Here is an example which combines some of the above directives: filling, alignment, field width and alternative output.

print '20. The value is <{0:#10d}> in base 10, <{0:#10b}> in base 2, <{0:<#10o}> in octal, <{0:^>#10x}> in hex and <{0:<#10X}> in hex upper'.format(28)
# prints
20. The value is <        28> in base 10, <   0b11100> in base 2, <0o34      > in octal, <^^^^^^0x1c> in hex and <0X1C      >

7. Working with Floats

Let us now check out the scene with formatting floating point numbers. The various types available are:

  • e: exponential or scientific notation
  • f: fixed point
  • g: “general” format. Uses e or f format depending on the value.

Check out these examples:

print '21. My height is <{0:}>\n       Using f - <{0:f}>\n       Using g - <{0:g}>\n       Using e - <{0:e}>'.format(1.8034)
# prints
21. My height is <1.8034>
       Using f - <1.803400>
       Using g - <1.8034>
       Using e - <1.803400e+00>

Specifying a width right-justifies the value within the width.

print '22. My height is <{0:20}>\n       Using f - <{0:20f}>\n       Using g - <{0:20g}>\n       Using e - <{0:20e}>'.format(1.8034)
# prints
22. My height is <              1.8034>
       Using f - <            1.803400>
       Using g - <              1.8034>
       Using e - <        1.803400e+00>

Using a precision and left-alignment.

print '23. My height is <{0:<20.8}>\n       Using f - <{0:<20.8f}>\n       Using g - <{0:^20.8g}>\n       Using e - <{0:^20.8e}>'.format(1.8034)
# prints
23. My height is <1.8034              >
       Using f - <1.80340000          >
       Using g - <       1.8034       >
       Using e - <   1.80340000e+00   >

You can use E and G also instead of e and g.

Conclusion

We have reviewed all the facilities available for python string formatting. Bookmark this page and use it as a tutorial or a manual.