# Dive Into Python

Python from novice to pro

Find:

## 8.6. Dictionary-based string formatting

Why did you learn about `locals` and `globals`? So you can learn about dictionary-based string formatting. As you recall, regular string formatting provides an easy way to insert values into strings. Values are listed in a tuple and inserted in order into the string in place of each formatting marker. While this is efficient, it is not always the easiest code to read, especially when multiple values are being inserted. You can't simply scan through the string in one pass and understand what the result will be; you're constantly switching between reading the string and reading the tuple of values.

There is an alternative form of string formatting that uses dictionaries instead of tuples of values.

### Example 8.13. Introducing dictionary-based string formatting

    >>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
    >>> "%(pwd)s" % params
    'secret'
    >>> "%(pwd)s is not a good password for %(uid)s" % params
    'secret is not a good password for sa'
    >>> "%(database)s of mind, %(database)s of body" % params
    'master of mind, master of body'

| Instead of a tuple of explicit values, this form of string formatting uses a dictionary, `params`. And instead of a simple `%s` marker in the string, the marker contains a name in parentheses. This name is used as a key in the `params` dictionary and subsitutes the corresponding value, `secret`, in place of the `%(pwd)s` marker.
| Dictionary-based string formatting works with any number of named keys. Each key must exist in the given dictionary, or the formatting will fail with a `KeyError`.
| You can even specify the same key twice; each occurrence will be replaced with the same value.

So why would you use dictionary-based string formatting? Well, it does seem like overkill to set up a dictionary of keys and values simply to do string formatting in the next line; it's really most useful when you happen to have a dictionary of meaningful keys and values already. Like `locals`.

### Example 8.14. Dictionary-based string formatting in `BaseHTMLProcessor.py`

        def handle_comment(self, text):
            self.pieces.append("<!--%(text)s-->" % locals())

Using the built-in `locals` function is the most common use of dictionary-based string formatting. It means that you can use the names of local variables within your string (in this case, `text`, which was passed to the class method as an argument) and each named variable will be replaced by its value. If `text` is `'Begin page footer'`, the string formatting `"<!--%(text)s-->" % locals()` will resolve to the string `'<!--Begin page footer-->'`.

### Example 8.15. More dictionary-based string formatting

        def unknown_starttag(self, tag, attrs):
            strattrs = "".join([' %s="%s"' % (key, value) for key, value in attrs])
            self.pieces.append("<%(tag)s%(strattrs)s>" % locals())

When this method is called, `attrs` is a list of key/value tuples, just like the `items` of a dictionary, which means you can use multi-variable assignment to iterate through it. This should be a familiar pattern by now, but there's a lot going on here, so let's break it down:

1. Suppose `attrs` is `[('href', 'index.html'), ('title', 'Go to home page')]`.
2. In the first round of the list comprehension, `key` will get `'href'`, and `value` will get `'index.html'`.
3. The string formatting `' %s="%s"' % (key, value)` will resolve to `' href="index.html"'`. This string becomes the first element of the list comprehension's return value.
4. In the second round, `key` will get `'title'`, and `value` will get `'Go to home page'`.
5. The string formatting will resolve to `' title="Go to home page"'`.
6. The list comprehension returns a list of these two resolved strings, and `strattrs` will join both elements of this list together to form `' href="index.html" title="Go to home page"'`.

| Now, using dictionary-based string formatting, you insert the value of `tag` and `strattrs` into a string. So if `tag` is `'a'`, the final result would be `'<a href="index.html" title="Go to home page">'`, and that is what gets appended to `self.pieces`.

Using dictionary-based string formatting with `locals` is a convenient way of making complex string formatting expressions more readable, but it comes with a price. There is a slight performance hit in making the call to `locals`, since `locals` builds a copy of the local namespace.