marky1991 marky1991 - 7 days ago 5
Python Question

Leaving values blank if not passed in str.format

I've run into a fairly simple issue that I can't come up with an elegant solution for.

I'm creating a string using

str.format
in a function that is passed in a
dict
of substitutions to use for the format. I want to create the string and format it with the values if they're passed and leave them blank otherwise.

Ex

kwargs = {"name": "mark"}
"My name is {name} and I'm really {adjective}.".format(**kwargs)


should return

"My name is mark and I'm really ."


instead of throwing a
KeyError
(Which is what would happen if we don't do anything).

Embarrassingly, I can't even come up with an inelegant solution for this problem. I guess I could solve this by just not using
str.format
, but I'd rather use the built-in (which mostly does what I want) if possible.

Note: I don't know in advance what keys will be used. I'm trying to fail gracefully if someone includes a key but doesn't put it in the kwargs dict. If I knew with 100% accuracy what keys would be looked up, I'd just populate all of them and be done with it.

Answer

You can follow the recommendation in PEP 3101 and subclass Formatter:

import string

class BlankFormatter(string.Formatter):
    def __init__(self, default=''):
        self.default=default

    def get_value(self, key, args, kwds):
        if isinstance(key, str):
            return kwds.get(key, self.default)
        else:
            Formatter.get_value(key, args, kwds)

kwargs = {"name": "mark", "adj": "mad"}     
fmt=BlankFormatter()
print fmt.format("My name is {name} and I'm really {adj}.", **kwargs)
# My name is mark and I'm really mad.
print fmt.format("My name is {name} and I'm really {adjective}.", **kwargs)
# My name is mark and I'm really .  

As of Python 3.2, you can use .format_map as an alternate:

class Default(dict):
    def __missing__(self, key):
        return '{'+key+'}'

kwargs = {"name": "mark"}

print("My name is {name} and I'm really {adjective}.".format_map(Default(kwargs)))

Prints:

My name is mark and I'm really {adjective}.
Comments