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.
"f" stands for floating point. The integer (here 3) represents the number of decimals after the point. "%. 3f" will print a real number with 3 figures after the point. – Kefeng91.
The format() method formats the specified value(s) and insert them inside the string's placeholder. The placeholder is defined using curly brackets: {}. Read more about the placeholders in the Placeholder section below. The format() method returns the formatted string.
Python's str. format() method of the string class allows you to do variable substitutions and value formatting. This lets you concatenate elements together within a string through positional formatting.
You can follow the recommendation in PEP 3101 and use a 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: return string.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 alternative:
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)))
which prints:
My name is mark and I'm really {adjective}.
Here is one option which uses collections.defaultdict
:
>>> from collections import defaultdict >>> kwargs = {"name": "mark"} >>> template = "My name is {0[name]} and I'm really {0[adjective]}." >>> template.format(defaultdict(str, kwargs)) "My name is mark and I'm really ."
Note that we aren't using **
to unpack the dictionary into keyword arguments anymore, and the format specifier uses {0[name]}
and {0[adjective]}
, which indicates that we should perform a key lookup on the first argument to format()
using "name"
and "adjective"
respectively. By using defaultdict
a missing key will result in an empty string instead of raising a KeyError.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With