Reputation: 4191
Is there any way to format string with dict but optionally without key errors?
This works fine:
opening_line = '%(greetings)s %(name)s !!!'
opening_line % {'greetings': 'hello', 'name': 'john'}
But let's say I don't know the name, and I would like to format above line
only for 'greetings'
. Something like,
opening_line % {'greetings': 'hello'}
Output would be fine even if:
'hii %(name)s !!!' # keeping name un-formatted
But this gives KeyError
while unpacking
Is there any way?
Upvotes: 11
Views: 16339
Reputation: 4025
You could subclass UserDict
and customize __missing__
to your liking with .format_map()
:
from collections import UserDict
class FormatMapper(UserDict):
def __missing__(self, key):
return f'{key=} is MISSING'
info = FormatMapper({'greetings': 'hello', 'not_name': 'john'})
opening_line = '{greetings} {name} !!!'
print(opening_line.format_map(info))
Output:
hello key='name' is MISSING !!!
Upvotes: 0
Reputation: 1453
I faced the same problem as yours and decided to create a library to solve this problem: pyformatting.
Here is the solution to your problem with pyformatting:
>>> from pyformatting import optional_format
>>> opening_line = '{greetings} {name} !!!'
>>> optional_format(opening_line, greetings='hii')
'hii {name} !!!'
The only problem is pyformatting doesn't support python 2. pyformatting supports python 3.1+ If i see any feedback on the need for 2.7 support i think i will add that support.
Upvotes: 0
Reputation: 1458
For the record:
info = {
'greetings':'DEFAULT',
'name':'DEFAULT',
}
opening_line = '{greetings} {name} !!!'
info['greetings'] = 'Hii'
print opening_line.format(**info)
# Hii DEFAULT !!!
Upvotes: 2
Reputation: 3154
Some alternates to defaultDict,
greeting_dict = {'greetings': 'hello'}
if 'name' in greeting_dict :
opening_line = '{greetings} {name}'.format(**greeting_dict)
else:
opening_line = '{greetings}'.format(**greeting_dict)
print opening_line
Maybe even more succinctly, use dictionary get to set per parameter defaults,
'{greetings} {name}'.format(greetings=greeting_dict.get('greetings','hi'),
name=greeting_dict.get('name',''))
Upvotes: 3
Reputation: 26164
Use defaultdict, this will allow you to specify a default value for keys which don't exist in the dictionary. For example:
>>> from collections import defaultdict
>>> d = defaultdict(lambda: 'UNKNOWN')
>>> d.update({'greetings': 'hello'})
>>> '%(greetings)s %(name)s !!!' % d
'hello UNKNOWN !!!'
>>>
Upvotes: 12