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?

有帮助吗?

解决方案

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 !!!'
>>> 

其他提示

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',''))

For the record:

info = {
    'greetings':'DEFAULT',
    'name':'DEFAULT',
    }
opening_line = '{greetings} {name} !!!'

info['greetings'] = 'Hii'
print opening_line.format(**info)
# Hii DEFAULT !!!

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.

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 !!!
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top