How do I format a string using a dictionary in python-3.x?

I am a big fan of using dictionaries to format strings. It helps me read the string format I am using as well as let me take advantage of existing dictionaries. For example:

class MyClass: def __init__(self): self.title = 'Title' a = MyClass() print 'The title is %(title)s' % a.__dict__ path = '/path/to/a/file' print 'You put your file here: %(path)s' % locals() 

However I cannot figure out the python 3.x syntax for doing the same (or if that is even possible). I would like to do the following

# Fails, KeyError 'latitude' geopoint = {'latitude':41.123,'longitude':71.091} print '{latitude} {longitude}'.format(geopoint) # Succeeds print '{latitude} {longitude}'.format(latitude=41.123,longitude=71.091) 
0

9 Answers

Is this good for you?

geopoint = {'latitude':41.123,'longitude':71.091} print('{latitude} {longitude}'.format(**geopoint)) 
6

To unpack a dictionary into keyword arguments, use **. Also,, new-style formatting supports referring to attributes of objects and items of mappings:

'{0[latitude]} {0[longitude]}'.format(geopoint) 'The title is {0.title}s'.format(a) # the a from your first example 
2

As Python 3.0 and 3.1 are EOL'ed and no one uses them, you can and should use str.format_map(mapping) (Python 3.2+):

Similar to str.format(**mapping), except that mapping is used directly and not copied to a dict. This is useful if for example mapping is a dict subclass.

What this means is that you can use for example a defaultdict that would set (and return) a default value for keys that are missing:

>>> from collections import defaultdict >>> vals = defaultdict(lambda: '<unset>', {'bar': 'baz'}) >>> 'foo is {foo} and bar is {bar}'.format_map(vals) 'foo is <unset> and bar is baz' 

Even if the mapping provided is a dict, not a subclass, this would probably still be slightly faster.

The difference is not big though, given

>>> d = dict(foo='x', bar='y', baz='z') 

then

>>> 'foo is {foo}, bar is {bar} and baz is {baz}'.format_map(d) 

is about 10 ns (2 %) faster than

>>> 'foo is {foo}, bar is {bar} and baz is {baz}'.format(**d) 

on my Python 3.4.3. The difference would probably be larger as more keys are in the dictionary, and


Note that the format language is much more flexible than that though; they can contain indexed expressions, attribute accesses and so on, so you can format a whole object, or 2 of them:

>>> p1 = {'latitude':41.123,'longitude':71.091} >>> p2 = {'latitude':56.456,'longitude':23.456} >>> '{0[latitude]} {0[longitude]} - {1[latitude]} {1[longitude]}'.format(p1, p2) '41.123 71.091 - 56.456 23.456' 

Starting from 3.6 you can use the interpolated strings too:

>>> f'lat:{p1["latitude"]} lng:{p1["longitude"]}' 'lat:41.123 lng:71.091' 

You just need to remember to use the other quote characters within the nested quotes. Another upside of this approach is that it is much faster than calling a formatting method.

3
print("{latitude} {longitude}".format(**geopoint)) 
2

Since the question is specific to Python 3, here's using the new f-string syntax, available since Python 3.6:

>>> geopoint = {'latitude':41.123,'longitude':71.091} >>> print(f'{geopoint["latitude"]} {geopoint["longitude"]}') 41.123 71.091 

Note the outer single quotes and inner double quotes (you could also do it the other way around).

2

The Python 2 syntax works in Python 3 as well:

>>> class MyClass: ... def __init__(self): ... self.title = 'Title' ... >>> a = MyClass() >>> print('The title is %(title)s' % a.__dict__) The title is Title >>> >>> path = '/path/to/a/file' >>> print('You put your file here: %(path)s' % locals()) You put your file here: /path/to/a/file 
1
geopoint = {'latitude':41.123,'longitude':71.091} # working examples. print(f'{geopoint["latitude"]} {geopoint["longitude"]}') # from above answer print('{geopoint[latitude]} {geopoint[longitude]}'.format(geopoint=geopoint)) # alternate for format method (including dict name in string). print('%(latitude)s %(longitude)s'%geopoint) # thanks @tcll 
2

Most answers formatted only the values of the dict.

If you want to also format the key into the string you can use dict.items():

geopoint = {'latitude':41.123,'longitude':71.091} print("{} {}".format(*geopoint.items())) 

Output:

('latitude', 41.123) ('longitude', 71.091)

If you want to format in an arbitry way, that is, not showing the key-values like tuples:

from functools import reduce print("{} is {} and {} is {}".format(*reduce((lambda x, y: x + y), [list(item) for item in geopoint.items()]))) 

Output:

latitude is 41.123 and longitude is 71.091

1

Use format_map to do what you want

print('{latitude} {longitude}'.format_map(geopoint)) 

This has the advantage that

  • the dictionary does not have to be blown up into parameters (compared to **geopoint) and that
  • the format string only has access to the provided map and not the entire scope of variables (compared to F-strings).

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like