congusbongus
congusbongus

Reputation: 14622

String formatting with argument from multiple return value function

How can I use functions that return multiple values as inputs to a format string, without getting the TypeError: not enough arguments for format string error?

>>> def foo():
...     return 1, 2
... 
>>> foo()
(1, 2)
>>> print "%d,%d,%d" % foo(), 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: not enough arguments for format string

Expected output: "1,2,3"

Upvotes: 2

Views: 1062

Answers (3)

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 250921

The reason print "%d,%d,%d" % foo(), 3 is not working is because Python is thinking you're trying to print two items here: "%d,%d,%d" % foo() and then 3. Due to this the first expression clearly fails because of in-sufficient number of items:

>>> def func():
...     print "%d,%d,%d" % foo(), 3
...     
>>> import dis
>>> dis.dis(func)
  2           0 LOAD_CONST               1 ('%d,%d,%d')
              3 LOAD_GLOBAL              0 (foo)
              6 CALL_FUNCTION            0
              9 BINARY_MODULO       
             10 PRINT_ITEM          
             11 LOAD_CONST               2 (3)
             14 PRINT_ITEM          
             15 PRINT_NEWLINE       
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE        

In fact even something like "%d,%d,%d" % foo() + (3,) won't work because I guess operator precedence comes into play here:

>>> def func():
    print "%d,%d,%d" % foo() + (3,)
...     
>>> dis.dis(func)
  2           0 LOAD_CONST               1 ('%d,%d,%d')
              3 LOAD_GLOBAL              0 (foo)
              6 CALL_FUNCTION            0
              9 BINARY_MODULO       
             10 LOAD_CONST               3 ((3,))
             13 BINARY_ADD          
             14 PRINT_ITEM          
             15 PRINT_NEWLINE       
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE 

A working version will be:

>>> print "%d,%d,%d" % (foo() + (3,))
1,2,3

Upvotes: 2

Cory Kramer
Cory Kramer

Reputation: 117856

A general solution to take an arbitrary number of arguments and print them with some delimiter would be to use str.join

def foo():
    return 1, 2

>>> print(','.join(map(str,foo())))
1,2

Another example

def bar():
    return 4,5,6,7

>>> print(','.join(map(str,bar())))
4,5,6,7

Upvotes: 0

congusbongus
congusbongus

Reputation: 14622

Element index

string.format() is more powerful and lets you access list elements or even attributes:

>>> print "{0[0]},{0[1]},{1}".format(foo(), 3)
1,2,3

Concatenate tuple

The problem with foo(), 3 is that it's a tuple and an integer, two different types. Instead you can create a 3-tuple via concatenation. If you use string.format() it's a bit trickier, as you need to unpack it first using the * operator so you can use it as arguments:

>>> foo() + (3,)
(1, 2, 3)

>>> print "%d,%d,%d" % (foo() + (3,))
1,2,3

>>> print "{},{},{}".format(*foo() + (3,))
1,2,3

Temporary variables

Of course, you can always do it this way, which is obvious but verbose:

>>> foo1, foo2 = foo()
>>> print "%d,%d,%d" % (foo1, foo2, 3)
1,2,3

Upvotes: 3

Related Questions