Chris Pickett

Python, .format & You

Python | Aug. 31, 2013, 11:19 a.m. | 1 min read

I'm probably slow to the party, but I just found out a couple months ago that python's `.format` command accepts keyword arguments, which makes for fantastically readable string formatting.

The Problem

You'll commonly see string formatting done with the % operator, which is great for really quick, simple string formatting, like:

name = "World"
"Hello %s" % name

but, when you have a more complicated string it can become unreadable very quickly. An, admittedly, convoluted example:

data = {
    'title': 'Hello World',
    'author': 'Ada Lovelace',
    'created_on': 'October, 1842',
    'body': 'The analytical engine.',
    'category': 'Programming',
    'tags': 'code, logic'
}

"%s by %s on %s\n%s\nPosted in %s -- tagged: %s" % (data['title'], data['author'], data['created_on'], data['body'], data['category'], data['tags'])

There are a few issues going on here, one is that the string itself contains no context around what %s means, or what it's going to be filled with. Also the arguments are all positional, which means that if we decided that we want to remove a parameter or change the way the string is put together we'd have to change the string as well as the position of the arguments which can lead to having hard to maintain code.

Along Came .format

.format without keyword arguments fixes one of these issues, as it allows you to reference the position of the argument in the string:

"{0} by {1}".format(data['title'], data['author'])

If at some point in the future we wanted to change the string around we would not need to change the arguments as we're referring to them by position.

Now We're Cooking With Kwargs

.format also gives us the ability to not just reference arguments by position but by using keywords:

"{title} by {author}".format(title=data['title'], author=data['author'])

This gives us the best of both worlds, not only is the string essentially readable without being formatted, but if we ever wanted to change the ouptut we'd only need to change the string and not the order of the arguments.

Using this we could even create a very rudimentary templating system. Re-using the example from above:

data = {
    'title': 'Hello World',
    'author': 'Ada Lovelace',
    'created_on': 'October, 1842',
    'body': 'The analytical engine.',
    'category': 'Programming',
    'tags': 'code, logic'
}

template_string = "{title} by {author} on {created_on}\n{body}\nPosted in {category} -- tagged: {tags}"
rendered = template_string.format(**data)

print(rendered)  # Would print: 'Hello World by Ada Lovelace on October, 1842\nThe analytical engine.\nPosted in Programming -- tagged: code, logic'

.format is even more powerful than I've shown here, so if you want to know more, go read the docs.

Comments

comments powered by Disqus