363

Ruby example:

name = "Spongebob Squarepants"
puts "Who lives in a Pineapple under the sea? \n#{name}."

The successful Python string concatenation is seemingly verbose to me.

Piper
  • 1,266
  • 3
  • 15
  • 26
Caste
  • 3,633
  • 2
  • 15
  • 5
  • 2
    The issue here is that `name` is a local variable lying in the string, and in Python you have to explicitly pass the dictionary of local variables to the string formatter if you want it to use them. – Katriel Dec 15 '10 at 14:58
  • This wasn't the original issue, but thanks. Your comment gave me a little better understanding of variable scope (something I'm still gaining ground with). :) – Caste Dec 15 '10 at 15:00
  • 1
    What do you think about this one, then? http://stackoverflow.com/questions/16504732/how-could-i-make-my-python-string-interpolation-implementation-work-across-impor – HarmonicaMuse May 12 '13 at 12:32
  • [PEP 215 -- String Interpolation](https://www.python.org/dev/peps/pep-0215/) - superseded by https://www.python.org/dev/peps/pep-0292/ – Mr_and_Mrs_D Oct 04 '15 at 14:33
  • 2
    See http://stackoverflow.com/a/33264516/55721 for this exact feature in 3.6 – dss539 Jul 20 '16 at 16:17

9 Answers9

437

Python 3.6 will add literal string interpolation similar to Ruby's string interpolation. Starting with that version of Python (which is scheduled to be released by the end of 2016), you will be able to include expressions in "f-strings", e.g.

name = "Spongebob Squarepants"
print(f"Who lives in a Pineapple under the sea? {name}.")

Prior to 3.6, the closest you can get to this is

name = "Spongebob Squarepants"
print("Who lives in a Pineapple under the sea? %(name)s." % locals())

The % operator can be used for string interpolation in Python. The first operand is the string to be interpolated, the second can have different types including a "mapping", mapping field names to the values to be interpolated. Here I used the dictionary of local variables locals() to map the field name name to its value as a local variable.

The same code using the .format() method of recent Python versions would look like this:

name = "Spongebob Squarepants"
print("Who lives in a Pineapple under the sea? {name!s}.".format(**locals()))

There is also the string.Template class:

tmpl = string.Template("Who lives in a Pineapple under the sea? $name.")
print(tmpl.substitute(name="Spongebob Squarepants"))
Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • @Caste see here: http://docs.python.org/library/stdtypes.html#string-formatting and post a follow up comment if you need any more details – mikej Dec 15 '10 at 13:59
  • I understand the basic gist of it, I don't fully understand all the additional symbols and text found in the example in the documentation however. Why the use of convert to string here: %(language)s What does the 3 in '03d' signify? Why after the string is there % \? The assignment of variables (if they are in fact variables) *after* the print expression confuses me also. Sorry if this is a pain! – Caste Dec 15 '10 at 14:07
  • 1
    The two basic formats used in the example are `%s` for a string and `%03d` for a number padded to 3 digits with leading zeroes. It could just be written `print "%s has %03d" % ("Python", 2)`. The example then makes use of putting a mapping key in brackets after the `%` which is a way of giving the placeholders meaningful names rather than relying on their order in the string. You then pass a dictionary that maps the key names to their values. That's why Sven is using the `locals()` function which returns a dict containing all your local variables so it will map `name` to the value of name – mikej Dec 15 '10 at 14:15
  • The required usage of a conversion type was what first confused me. So, using the documentation terminology. The % starts the specifier. There is no conversion flag for (language), just a conversion type (the trailing 's'); (number) however has one (or two) conversion flags which is '0' (and '3' respectively). The 'd' is the conversion type and signifies it is an integer. Did I understand correctly? – Caste Dec 15 '10 at 14:32
  • @Caste: Yes, that's basically right. Note that you could always use a `s` as a conversion type -- Python can convert just about anything to a string. But of course you would lose the special formatting capabilities of other conversion types. – Sven Marnach Dec 15 '10 at 14:37
  • @Caste: If string interpolation using `%` confuses you, you caould also have a look at the [new string formatting apabilities](http://docs.python.org/library/string.html#formatstrings) of recent versions of Python. They are meant to eventually replace `%`. – Sven Marnach Dec 15 '10 at 14:40
  • Ah yes. Thank you Sven. It's not so much that it confuses me. It just makes no sense to have the method act like that (this is of course subjective). Testing the .format method clears all this up! :) – Caste Dec 15 '10 at 14:52
  • @flaviotruzzi That's what the first sentence of the answer says, isn't it? – Sven Marnach Aug 08 '17 at 11:55
151

Since Python 2.6.X you might want to use:

"my {0} string: {1}".format("cool", "Hello there!")
Nathan Hinchey
  • 1,191
  • 9
  • 30
EinLama
  • 2,376
  • 1
  • 14
  • 10
  • 27
    Note that the `%` operator for string interpolation is **not** deprecated in Python 3.x. http://docs.python.org/dev/py3k/whatsnew/3.0.html#changes-already-present-in-python-2-6 announces the plan to deprecate `%` starting in 3.1, but this never happened. – Sven Marnach Dec 15 '10 at 14:52
  • 8
    %-syntax still lives on in Python 3 (not deprecated as of Python 3.2) – Corey Goldberg Dec 15 '10 at 17:49
  • 10
    Just a note: the number in `{}` can me eliminated. – draw Mar 30 '15 at 02:55
32

I've developed the interpy package, that enables string interpolation in Python.

Just install it via pip install interpy. And then, add the line # coding: interpy at the beginning of your files!

Example:

#!/usr/bin/env python
# coding: interpy

name = "Spongebob Squarepants"
print "Who lives in a Pineapple under the sea? \n#{name}."
Syrus Akbary Nieto
  • 1,249
  • 12
  • 20
29

Python's string interpolation is similar to C's printf()

If you try:

name = "SpongeBob Squarepants"
print "Who lives in a Pineapple under the sea? %s" % name

The tag %s will be replaced with the name variable. You should take a look to the print function tags: http://docs.python.org/library/functions.html

bbonamin
  • 30,042
  • 7
  • 40
  • 49
Oleiade
  • 6,156
  • 4
  • 30
  • 42
28

String interpolation is going to be included with Python 3.6 as specified in PEP 498. You will be able to do this:

name = 'Spongebob Squarepants'
print(f'Who lives in a Pineapple under the sea? \n{name}')

Note that I hate Spongebob, so writing this was slightly painful. :)

kirbyfan64sos
  • 10,377
  • 6
  • 54
  • 75
4

You can also have this

name = "Spongebob Squarepants"
print "Who lives in a Pineapple under the sea? \n{name}.".format(name=name)

http://docs.python.org/2/library/string.html#formatstrings

Quan To
  • 697
  • 3
  • 10
  • I don't believe OP intended the `#` to be printed. They are just using Ruby syntax. – jaynp Jan 03 '15 at 21:02
  • You're right. I edited the answer. I am not familiar with Ruby, so I thought the `#` character would be printed. – Quan To Feb 04 '15 at 11:14
3
import inspect
def s(template, **kwargs):
    "Usage: s(string, **locals())"
    if not kwargs:
        frame = inspect.currentframe()
        try:
            kwargs = frame.f_back.f_locals
        finally:
            del frame
        if not kwargs:
            kwargs = globals()
    return template.format(**kwargs)

Usage:

a = 123
s('{a}', locals()) # print '123'
s('{a}') # it is equal to the above statement: print '123'
s('{b}') # raise an KeyError: b variable not found

PS: performance may be a problem. This is useful for local scripts, not for production logs.

Duplicated:

Community
  • 1
  • 1
Paulo Cheque
  • 2,797
  • 21
  • 22
3

Python 3.6 and newer have literal string interpolation using f-strings:

name='world'
print(f"Hello {name}!")
Alejandro Silva
  • 8,808
  • 1
  • 35
  • 29
2

For old Python (tested on 2.4) the top solution points the way. You can do this:

import string

def try_interp():
    d = 1
    f = 1.1
    s = "s"
    print string.Template("d: $d f: $f s: $s").substitute(**locals())

try_interp()

And you get

d: 1 f: 1.1 s: s
Michael Fox
  • 3,632
  • 1
  • 17
  • 27