I want to format and print data from a dictionary with the keyword unpacking operator **
.
The format string possibly refers to many keywords and the dictionary may not have all the required keys. For the missing keys, I would like to use the string 'N/A' as a default value.
I would like a clever solution for this default-ing problem, possibly using a defaultdict
.
Here is a first solution using a regular dict
.
# Cumbersome solution with dict
format_str = '{date} {version} {comment}'
data = dict()
data['date'] = 'today'
data['version'] = 'v1'
data['comment'] = 'N/A' # I want to avoid this
print format_str.format(**data)
# prints: today v1 N/A
I would like to avoid the explicit assignment of 'N/A' for missing keys.
The following solution also uses a regular dict
and analyzes the format string to build the list of keywords:
# Another solutions with handmade defaults for missing keys
format_str = '{date} {version} {comment}'
data = dict()
data['date'] = 'today'
data['version'] = 'v1'
import re
for k in re.findall('{(\w+)}', format_str):
if k not in data:
data[k] = 'N/A'
print format_str.format(**data)
# prints: today v1 N/A
This solution with re.findall
is not really elegant nor robust since the syntax of format string is much more complex than the above {(\w+)}
.
The following solution would be my favorite one… if it did not fail for an obvious reason.
# Failed attempt with defaultdict
from collections import defaultdict
format_str = '{date} {version} {comment}'
data = defaultdict(lambda x:'N/A')
data['date'] = 'today'
data['version'] = 'v1'
print format_str.format(**data)
# raises KeyError: 'comment'
The problem here is that **
actually unpacks the keywords in data
, so format
does not search data
for the requested keywords and thus does not give data
the opportunity to provide its default value.
Is there a solution to this ?
Eg is there an alternative format
function which would actually call data.get(kwd)
and thus get the N/A
s?