user2281204
user2281204

Reputation: 83

Why does printing a variable and function call together in this code give an error?

I've started learning Python through Zed Shaw's "Learn Python the hard way" (link here)

In this example I changed the code snippet below:

def secret_formula(started):
    jelly_beans = started * 500
    jars = jelly_beans / 1000
    crates = jars / 100
    return jelly_beans, jars, crates


start_point = 10000
beans, jars, crates = secret_formula(start_point)

print "With a starting point of: %d" % start_point
print "We'd have %d beans, %d jars, and %d crates." % (beans, jars, crates)

to this:

def secret_formula(started):
    jelly_beans = started * 500
    jars = jelly_beans / 1000
    crates = jars / 100
    return jelly_beans, jars, crates


start_point = 10000
print "With a starting point of: %d we'd have %d, %d, %d" % (start_point,secret_formula(start_point))

Why does it give the error:

TypeError: float argument required, not tuple

when this line works fine?

print "We'd have %d beans, %d jars, and %d crates." % secret_formula(start_point)

Upvotes: 2

Views: 170

Answers (3)

Burhan Khalid
Burhan Khalid

Reputation: 174662

Since the return value of secret_formula is a tuple, when you write:

print "We'd have %d beans, %d jars, and %d crates." % secret_formula(start_point)

It becomes

print "We'd have %d beans, %d jars, and %d crates." % (1, 2, 3)

To make it work correctly in your example, you have two options:

  1. Use the new .format() function, with argument unpacking:

    print "With a starting point of: {} we'd have {}, {}, {}".format(start_point,*secret_formula(start_point))
    
  2. Make start_point into a tuple, then add it with the result of the function call:

    print "With a starting point of: %d we'd have %d, %d, %d" % ((start_point,)+secret_formula(start_point))
    

For simple readability, I'd go with option #1

Upvotes: 2

PM 2Ring
PM 2Ring

Reputation: 55489

Unfortunately, the *secret_formula(start_point) construction suggested by Burhan Khalid doesn't work outside of argument lists. But we can use tuple concatenation:

def secret_formula(started):
    jelly_beans = started * 500
    jars = jelly_beans / 1000
    crates = jars / 100
    return jelly_beans, jars, crates


start_point = 10000

print "With a starting point of: %d we'd have %d, %d, %d" % ((start_point,) + secret_formula(start_point)) 

output

With a starting point of: 10000 we'd have 5000000, 5000, 50

(start_point,) creates a one element tuple, so we can add it to the tuple returned by secret_formula(). We need the outer parentheses because % has higher precedence than +.

Upvotes: 0

ohmu
ohmu

Reputation: 19780

The problem is secret_formula() returns a 3-tuple:

(jelly_beans, jars, crates)

So the original print statement:

print "With a starting point of: %d we'd have %d, %d, %d" % (start_point,secret_formula(start_point))

Becomes:

print "With a starting point of: %d we'd have %d, %d, %d" % (start_point, (jelly_beans, jars, crates))

The specific TypeError you are getting is because the tuple (jelly_beans, jars, crates) is the second argument which must be of format %d which indicates is a decimal integer. Tuples are not implicitly convertible into a int or float. I'm not entirely sure why it says a "float argument [is] required" instead of an integer one though.

Also note that the print statement contains 4 %ds so it expects 4 separate values. You gave it 2:

  1. start_point.

  2. (jelly_beans, jars, crates).

The reason the second print statement works fine is because the % operator accepts either a single value, or multiple values packed into a tuple which secret_formula() happens to return.

Upvotes: 4

Related Questions