20

What is wrong in this piece of code?

dic = { 'fruit': 'apple', 'place':'table' }
test = "I have one {fruit} on the {place}.".format(dic)
print(test)

>>> KeyError: 'fruit'
Kev
  • 115,559
  • 50
  • 294
  • 378
bogdan
  • 8,194
  • 10
  • 36
  • 42
  • Possible duplicate of https://stackoverflow.com/questions/5952344/how-do-i-format-a-string-using-a-dictionary-in-python-3-x – Frank May 16 '19 at 20:17

3 Answers3

40

Should be

test = "I have one {fruit} on the {place}.".format(**dic)

Note the **. format() does not accept a single dictionary, but rather keyword arguments.

jfs
  • 374,366
  • 172
  • 933
  • 1,594
Sven Marnach
  • 530,615
  • 113
  • 910
  • 808
  • Thanks, it works. Can you update the answer to explain why I have to add `**` before the dictionary? – bogdan Jun 03 '11 at 16:08
  • 4
    @bogdan, the `**` indicates that the dictionary should be expanded to a list of keyword parameters. The `format` method doesn't take a dictionary as a parameter, but it does take keyword parameters. – Mark Ransom Jun 03 '11 at 16:14
  • @bogdan: Added two links to my answer. The reason basically is "because the documentation says so". – Sven Marnach Jun 03 '11 at 16:14
  • 1
    @bogdan That just tells Python that you are providing a dictionary to the function so that it can provide the values in the dictionary, rather than the dictionary itself. You can do the same when calling any function. If function 'f' takes the args 'a','b', and 'c', you could use `dic = {'a':1,'b':2,'c':3}` and call `f(**dic)`. – Michael Smith Jun 03 '11 at 16:19
  • 4
    The reason is that `"I have one {0[fruit]} on the {0[place]}.".format(dic)` works too - `dic` is the 0th positional argument here and you can access it's keys in the template. – Jochen Ritzel Jun 03 '11 at 16:24
11

There is ''.format_map() function since Python 3.2:

test = "I have one {fruit} on the {place}.".format_map(dic)

The advantage is that it accepts any mapping e.g., a class with __getitem__ method that generates values dynamically or collections.defaultdict that allows you to use non-existent keys.

It can be emulated on older versions:

from string import Formatter

test = Formatter().vformat("I have one {fruit} on the {place}.", (), dic)
jfs
  • 374,366
  • 172
  • 933
  • 1,594
1

You can use the following code too:

dic = { 'fruit': 'apple', 'place':'table' }
print "I have one %(fruit)s on the %(place)s." % dic

If you want to know more about format method use: http://docs.python.org/library/string.html#formatspec

Artsiom Rudzenka
  • 26,491
  • 4
  • 32
  • 51