marky1991 marky1991 - 10 months ago 40
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 Source

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}.