New style formatting with tuple as argument

Question:

Why can’t I use tuple as argument to formatter in new style (“string”.format())? It works fine in old style (“string” %)?

This code works:

>>> tuple = (500000, 500, 5)
... print "First item: %d, second item: %d and third item: %d." % tuple

    First item: 500000, second item: 500 and third item: 5.

And this doesn’t:

>>> tuple = (500000, 500, 5)
... print("First item: {:d}, second item: {:d} and third item: {:d}."
...       .format(tuple))

    Traceback (most recent call last):
     File "<stdin>", line 2, in <module>
    ValueError: Unknown format code 'd' for object of type 'str'

Even with {!r}

>>> tuple = (500000, 500, 5)
... print("First item: {!r}, second item: {!r} and third item: {!r}."
...       .format(tuple))

    Traceback (most recent call last):
     File "<stdin>", line 2, in <module>
    IndexError: tuple index out of range

Though it works with that way:

>>> print("First item: {!r}, second item: {!r} and third item: {!r}."
...       .format(500000, 500, 50))

    First item: 500000, second item: 500 and third item: 5.
Asked By: Mark Luther

||

Answers:

The old way of formatting used a binary operator, %. By its nature, it can only accept two arguments. The new way of formatting uses a method. Methods can take any number of arguments.

Since you sometimes need to pass multiple things to format and it’s somewhat clumsy to create tuples with one item all the time, the old-style way came up with a hack: if you pass it as a tuple, it will use the contents of the tuple as the things to format. If you pass it something other than a tuple, it will use that as the only thing to format.

The new way does not need such a hack: as it is a method, it can take any number of arguments. As such, multiple things to format will need to be passed as separate arguments. Luckily, you can unpack a tuple into arguments using *:

print("First item: {:d}, second item: {:d} and third item: {:d}.".format(*tuple))
Answered By: icktoofay

As icktoofay explained, in the old style of formatting, if you passed in a tuple, Python would automatically unpack it.

However, you can’t use a tuple with the str.format method because Python thinks that you’re only passing in one argument. You would have to unpack the tuple with the * operator to pass in each of the elements as an individual argument.

>>> t = (500000, 500, 5)
>>> "First item: {:d}, second item: {:d} and third item: {:d}.".format(*t)
First item: 500000, second item: 500 and third item: 5.

Also, you would have noticed I renamed your tuple variable to t – don’t use builtin names for variables, as you will overwrite them and that could cause problems down the track.

Answered By: Volatility

It is actually possible to use a tuple as an argument to format(), if you manually index the tuple inside the curly braces:

>>> t = (500000, 500, 5)
>>> print("First item: {0[0]:d}, second item: {0[1]:d} and third item: {0[2]:d}.".format(t))
First item: 500000, second item: 500 and third item: 5.

I find this less clear than the * approach, though.

Answered By: 1''
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.