TAGS :Viewed: 3 - Published at: a few seconds ago

[ `"...".format(**ctx)` which skips unknown keys? ]

Is it possible to create a dict-like object that can be used in str.format() and that leaves unknown substitutions, i.e.:

ctx = Context(source='foo', name='bar')
print "{source}/static/{name}-{version}.min.css".format(**ctx)

should print

"foo/static/bar-{version}.min.css"

I tried with a simple dict subclass:

class Context(dict):
    def __getitem__(self, k):
        if k not in self: return '{%s}' % k
        return dict.__getitem__(self, k)

but that errors with KeyError: 'version'

Answer 1


Python 3 introduced str.format_map for this:

class Context(dict):
    def __missing__(self, key):
        return '{%s}' % key

ctx = Context(source='foo', name='bar')
print("{source}/static/{name}-{version}.min.css".format_map(ctx))

prints

foo/static/bar-{version}.min.css

One of the changes involved in adding format_map had the probably-unintended side effect that Python 3's str.format will also accept dict subclasses, but mappings that don't subclass dict need to be passed to format_map. I believe this new behavior of str.format is technically a bug. In any case, format_map is probably safer.

For Python 2, the issue on the Python bug tracker leading to str.format_map's inclusion suggests using string.Formatter.vformat:

import string
print string.Formatter().vformat("{source}/static/{name}-{version}.min.css", (), ctx)

Answer 2


class Context(dict):
    def __getitem__(self, k):
        return self.get(k, '{%s}' % k)

>>> ctx = Context(source='foo', name='bar')
>>>
>>> print("{source}/static/{name}-{version}.min.css".format(**ctx))
foo/static/bar-{version}.min.css