String substitution in Python 3?

The % operator will work, the syntax for which is simple:

>>> subs = 'world'
>>> 'Hello %s' % subs
'Hello world'

The new syntax for string formatting allows for additional options, heres a snippet from the python docs overviewing the basic ways to use the newer str.format() method:

>>> '{0}, {1}, {2}'.format('a', 'b', 'c')
'a, b, c'
>>> '{}, {}, {}'.format('a', 'b', 'c')  # 2.7+ only
'a, b, c'
>>> '{2}, {1}, {0}'.format('a', 'b', 'c')
'c, b, a'
>>> '{2}, {1}, {0}'.format(*'abc')      # unpacking argument sequence
'c, b, a'
>>> '{0}{1}{0}'.format('abra', 'cad')   # arguments' indices can be repeated
'abracadabra'

So using the newer syntax, a simple resolution to your problem would be:

>>> subs = 'world'
>>> 'Hello {}'.format(subs)
'Hello world'

Like others pointed out already, there are two ways to do string formatting in Python at the moment.

Python 3.6 will introduce a third option. Details can be found here:

PEP 0498 -- Literal String Interpolation

>>> name = 'Fred' 
>>> f'He said his name is {name!r}.'  
"He said his name is 'Fred'."

You have two three options for formatting:

  • The old python2 style % operator that works with C-printf-style format strings
  • The new python3 style format() method of the string. Because of backporting you can use this option in both python2 and python3.
  • The even newer python 3.6+ f-strings that aren't backported to python2: these allow you to specify expressions inside your string literals

The % formatter that accepts C-printf-style format strings:

"Hello %s" % subs
"Hello %s%s" % (subs, '.')
my_dict = {'placeholder_name': 'world', 'period': '.'}
"Hello %(placeholder_name)s%(period)s" % my_dict

Note that in python the %s format specifier accepts any kind of object (integer, class instance, etc) as input and converts it to a string with the str() operator that is quite convenient. The same is true about %r that calls repr() on the substitutable input object. You need other format specifiers like %f only if you want to do type (eg.: float) specific format parametrization (like %.5f).

The format() method:

"Hello {}".format(subs)
"Hello {placeholder_name}".format(placeholder_name=subs)

Of course placeholder_name could also be subs, I just used a different name to clarify things. The following would work just like the above solution:

"Hello {subs}".format(subs=subs)

In python positional arguments can also be passed to a function call from a list or tuple, and keyword arguments can also be passed from a dictionary if you want to exploit more dynamic features of the language:

my_tuple = ('world', '.')
"Hello {}{}".format(*my_tuple)
my_dict = {'subs': 'world', 'period': '.'}
"Hello {subs}{period}".format(**my_dict)

We could complicate things by parametrizing the format string, check out the docs for the format() method for more.

If you have multiple things to substitute then I highly recommend using named placeholders (with the keyword args of format()) instead of fiddling with argument indexes because it usually results in easier to read code. If there are multiple things to substitute then it can also reduce the occurrence of bugs.

The python 3.6+ f-strings:

>>> x=5
>>> y=6
>>> f'woof {x*y} meow'
'woof 30 meow'

Tags:

Python 3.X