Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Formatting Python Strings
In the previous tutorial in this introductory series, you got a first look at how you can format your strings with Python f-strings. You’ll learn more about this technique towards the end of this tutorial.
Since f-strings are comparably new to the Python language, it’s good for you to be familiar with a second, slightly older technique as well. You’re likely to encounter it in older Python code.
In this tutorial, you’ll learn about:
- The string
.format()method - The formatted string literal, or f-string
You’ll learn about these formatting techniques in detail and add them to your Python string formatting toolkit.
Note: There’s a standard module called string containing a class called Template, which also provides some string formatting through interpolation. A related technique, the string modulo operator, provides more or less the same functionality. You won’t cover either of these techniques in this tutorial, but you’ll want to read up on the string modulo operator if you have to work with code written in Python 2.
You might notice that there are a lot of different ways to format strings in Python, which breaks with one of Python’s very own mantras:
There should be one– and preferably only one –obvious way to do it. —Tim Peters, The Zen of Python
The different string formatting techniques have developed historically over the years that Python has existed and grown. Older techniques are kept around to ensure backward compatibility, and some even have specific use cases.
If you’re getting started with Python and you’re looking for a single way to format your strings, then stick with Python’s f-strings. If you’ve encountered strange-looking string format code and want to know more, or you need to work with older versions of Python, then it’s a good idea to learn about the other techniques as well.
The Python String .format() Method
The Python string .format() method was introduced in version 2.6. It’s similar in many ways to the string modulo operator, but .format() goes well beyond in versatility. The general form of a Python .format() call is shown below:
<template>.format(<positional_argument(s)>, <keyword_argument(s)>)
Note that this is a method, not an operator. You call the method on <template>, which is a string containing replacement fields. The <positional_arguments> and <keyword_arguments> to the method specify values that are inserted into <template> in place of the replacement fields. The resulting formatted string is the method’s return value.
In the <template> string, replacement fields are enclosed in curly braces ({}). Anything not contained in curly braces is literal text that’s copied directly from the template to the output. If you need to include a literal curly bracket character, like { or }, in the template string, then you can escape this character by doubling it:
>>> '{{ {0} }}'.format('foo')
'{ foo }'
Now the curly braces are included in your output.
The String .format() Method: Arguments
Let’s start with a quick example to get you acquainted before you dive into more detail on how to use this method in Python to format strings. Using the older formatting technique with the string modulo operator, the code would be a little hard to read:
>>> print('%d %s cost $%.2f' % (6, 'bananas', 1.74))
6 bananas cost $1.74
In the example above, you used the string modulo operator to format the string. For better readability, you can use Python’s string .format() method to obtain the same result:
>>> print('{0} {1} cost ${2}'.format(6, 'bananas', 1.74))
6 bananas cost $1.74
In this example, <template> is the string '{0} {1} cost ${2}'. The replacement fields are {0}, {1}, and {2}, which contain numbers that correspond to the zero-based positional arguments 6, 'bananas', and 1.74. Each positional argument is inserted into the template in place of its corresponding replacement field:

The next example uses keyword arguments instead of positional parameters to produce the same result:
>>> print('{quantity} {item} cost ${price}'.format(
... quantity=6,
... item='bananas',
... price=1.74))
6 bananas cost $1.74
In this case, the replacement fields are {quantity}, {item}, and {price}. These fields specify keywords that correspond to the keyword arguments quantity=6, item='bananas', and price=1.74. Each keyword value is inserted into the template in place of its corresponding replacement field:

You’ll learn more about positional and keywords arguments there in the next tutorial in this introductory series, which explores functions and argument passing. For now, the two sections that follow will show you how these are used with the Python .format() method.
Positional Arguments
Positional arguments are inserted into the template in place of numbered replacement fields. Like list indexing, the numbering of replacement fields is zero-based. The first positional argument is numbered 0, the second is numbered 1, and so on:
>>> '{0}/{1}/{2}'.format('foo', 'bar', 'baz')
'foo/bar/baz'
Note that replacement fields don’t have to appear in the template in numerical order. They can be specified in any order, and they can appear more than once:
>>> '{2}.{1}.{0}/{0}{0}.{1}{1}.{2}{2}'.format('foo', 'bar', 'baz')
'baz.bar.foo/foofoo.barbar.bazbaz'
When you specify a replacement field number that’s out of range, you’ll get an error. In the following example, the positional arguments are numbered 0, 1, and 2, but you specify {3} in the template:
>>> '{3}'.format('foo', 'bar', 'baz')
Traceback (most recent call last):
File "<pyshell#26>", line 1, in <module>
'{3}'.format('foo', 'bar', 'baz')
IndexError: tuple index out of range
This raises an IndexError exception.
Starting with Python 3.1, you can omit the numbers in the replacement fields, in which case the interpreter assumes sequential order. This is referred to as automatic field numbering:
>>> '{}/{}/{}'.format('foo', 'bar', 'baz')
'foo/bar/baz'
When you specify automatic field numbering, you must provide at least as many arguments as there are replacement fields:
>>> '{}{}{}{}'.format('foo','bar','baz')
Traceback (most recent call last):
File "<pyshell#27>", line 1, in <module>
'{}{}{}{}'.format('foo','bar','baz')
IndexError: tuple index out of range
In this case, there are four replacement fields in the template but only three arguments, so an IndexError exception occurs. On the other hand, it’s fine if the arguments outnumber the replacement fields. The excess arguments simply aren’t used:
>>> '{}{}'.format('foo', 'bar', 'baz')
'foobar'
Here, the argument 'baz' is ignored.
Note that you can’t intermingle these two techniques:
>>> '{1}{}{0}'.format('foo','bar','baz')
Traceback (most recent call last):
File "<pyshell#28>", line 1, in <module>
'{1}{}{0}'.format('foo','bar','baz')
ValueError: cannot switch from manual field specification to automatic field
numbering
When you use Python to format strings with positional arguments, you must choose between either automatic or explicit replacement field numbering.
Keyword Arguments
Keyword arguments are inserted into the template string in place of keyword replacement fields with the same name:
>>> '{x}/{y}/{z}'.format(x='foo', y='bar', z='baz')
'foo/bar/baz'
In this example, the values of the keyword arguments x, y, and z take the place of the replacement fields {x}, {y}, and {z}, respectively.
If you refer to a keyword argument that’s missing, then you’ll see an error:
>>> '{x}/{y}/{w}'.format(x='foo', y='bar', z='baz')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'w'
Here, you specify replacement field {w}, but there’s no corresponding keyword argument named w. Python raises a KeyError exception.
While you have to specify positional arguments in sequential order, but you can specify keyword arguments in any arbitrary order:
>>> '{0}/{1}/{2}'.format('foo', 'bar', 'baz')
'foo/bar/baz'
>>> '{0}/{1}/{2}'.format('bar', 'baz', 'foo')
'bar/baz/foo'
>>> '{x}/{y}/{z}'.format(x='foo', y='bar', z='baz')
'foo/bar/baz'
>>> '{x}/{y}/{z}'.format(y='bar', z='baz', x='foo')
'foo/bar/baz'
You can specify both positional and keyword arguments in one Python .format() call. Just note that, if you do so, then all the positional arguments must appear before any of the keyword arguments:
>>> '{0}{x}{1}'.format('foo', 'bar', x='baz')
'foobazbar'
>>> '{0}{x}{1}'.format('foo', x='baz', 'bar')
File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
In fact, the requirement that all positional arguments appear before any keyword arguments doesn’t apply only to Python format methods. This is generally true of any function or method call. You’ll learn more about this in the next tutorial in this series, which explores functions and function calls.
In all the examples shown so far, the values you passed to the Python .format() method have been literal values, but you may specify variables as well:
>>> x = 'foo'
>>> y = 'bar'
>>> z = 'baz'
>>> '{0}/{1}/{s}'.format(x, y, s=z)
'foo/bar/baz'
In this case, you pass the variables x and y as positional parameter values and z as a keyword parameter value.
The String .format() Method: Simple Replacement Fields
As you’ve seen, when you call Python’s .format() method, the <template> string contains replacement fields. These indicate where in the template to insert the arguments to the method. A replacement field consists of three components:
{[<name>][!<conversion>][:<format_spec>]}
These components are interpreted as follows:
| Component | Meaning |
|---|---|
<name> |
Specifies the source of the value to be formatted |
<conversion> |
Indicates which standard Python function to use to perform the conversion |
<format_spec> |
Specifies more detail about how the value should be converted |
Each component is optional and may be omitted. Let’s take a look at each component in more depth.
The <name> Component
The <name> component is the first portion of a replacement field:
{[<name>][!<conversion>][:<format_spec>]}
<name> indicates which argument from the argument list is inserted into the Python format string in the given location. It’s either a number for a positional argument or a keyword for a keyword argument. In the following example, the <name> components of the replacement fields are 0, 1, and baz, respectively:
>>> x, y, z = 1, 2, 3
>>> '{0}, {1}, {baz}'.format(x, y, baz=z)
'1, 2, 3'
If an argument is a list, then you can use indices with <name> to access the list’s elements:
>>> a = ['foo', 'bar', 'baz']
>>> '{0[0]}, {0[2]}'.format(a)
'foo, baz'
>>> '{my_list[0]}, {my_list[2]}'.format(my_list=a)
'foo, baz'
Similarly, you can use a key reference with <name> if the corresponding argument is a dictionary:
>>> d = {'key1': 'foo', 'key2': 'bar'}
>>> d['key1']
'foo'
>>> '{0[key1]}'.format(d)
'foo'
>>> d['key2']
'bar'
>>> '{my_dict[key2]}'.format(my_dict=d)
'bar'
You can also reference object attributes from within a replacement field. In the previous tutorial in this series, you learned that virtually every item of data in Python is an object. Objects may have attributes assigned to them that are accessed using dot notation:
obj.attr
Here, obj is an object with an attribute named attr. You use dot notation to access the object’s attribute. Let’s see an example. Complex numbers in Python have attributes named .real and .imag that represent the real and imaginary portions of the number. You can access these using dot notation as well:
>>> z = 3+5j
>>> type(z)
<class 'complex'>
>>> z.real
3.0
>>> z.imag
5.0
There are several upcoming tutorials in this series on object-oriented programming, in which you’ll learn a great deal more about object attributes like these.
The relevance of object attributes in this context is that you can specify them in a Python .format() replacement field:
>>> z
(3+5j)
>>> 'real = {0.real}, imag = {0.imag}'.format(z)
'real = 3.0, imag = 5.0'
As you can see, it’s relatively straightforward in Python to format components of complex objects using the .format() method.
The <conversion> Component
The <conversion> component is the middle portion of a replacement field:
{[<name>][!<conversion>][:<format_spec>]}
Python can format an object as a string using three different built-in functions:
str()repr()ascii()
By default, the Python .format() method uses str(), but in some instances, you may want to force .format() to use one of the other two. You can do this with the <conversion> component of a replacement field. The possible values for <conversion> are shown in the table below:
| Value | Meaning |
|---|---|
!s |
Convert with str() |
!r |
Convert with repr() |
!a |
Convert with ascii() |
The following examples force Python to perform string conversion using str(), repr(), and ascii(), respectively:
>>> '{0!s}'.format(42)
'42'
>>> '{0!r}'.format(42)
'42'
>>> '{0!a}'.format(42)
'42'
In many cases, the result is the same regardless of which conversion function you use, as you can see in the example above. That being said, you won’t often need the <conversion> component, so you won’t spend a lot of time on it here. However, there are situations where it makes a difference, so it’s good to be aware that you have the capability to force a specific conversion function if you need to.
The <format_spec> Component
The <format_spec> component is the last portion of a replacement field:
{[<name>][!<conversion>][:<format_spec>]}
<format_spec> represents the guts of the Python .format() method’s functionality. It contains information that exerts fine control over how values are formatted prior to being inserted into the template string. The general form is this:
:
[[<fill>]<align>][<sign>][#][0][<width>][<group>][.<prec>][<type>]
The ten subcomponents of <format_spec> are specified in the order shown. They control formatting as described in the table below:
| Subcomponent | Effect |
|---|---|
: |
Separates the <format_spec> from the rest of the replacement field |
<fill> |
Specifies how to pad values that don’t occupy the entire field width |
<align> |