Sean Valdivia Sean Valdivia - 5 months ago 14
Python Question

String Formatting Confusion

O'Reilly's Learn Python Powerful Object Oriented Programming by Mark Lutz teaches different ways to format strings.

This following code has me confused. I am interpreting 'ham' as filling the format place marker at index zero, and yet it still pops up at index one of the outputted string. Please help me understand what is actually going on.

Here is the code:

template = '{motto}, {0} and {food}'
template.format('ham', motto='spam', food='eggs')

And here is the output:

'spam, ham and eggs'

I expected:

'ham, spam and eggs'


The only thing you have to understand is that {0} refers to the first (zeroeth) unnamed argument sent to format(). We can see this to be the case by removing all unnamed references and trying to use a linear fill-in:

>>> "{motto}".format("boom")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'motto'

You would expect that 'boom' would fill in 'motto' if this is how it works. But, instead, format() looks for a parameter named 'motto'. The key hint here is the KeyError. Similarly, if it were just taking the sequence of parameters passed to format(), then this wouldn't error, either:

>>> "{0} {1}".format('ham', motto='eggs')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: tuple index out of range

Here, format() is looking for the second unnamed argument in the parameter list - but that doesn't exist so it gets a 'tuple index out of range' error. This is just the difference between the unnamed (which are positionally sensitive) and named arguments passed in Python.

See this post to understand the difference between these types arguments, known as 'args' and 'kwargs'.