Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: variable bindings in recursive functions

I came across some weirdness in Python using a function similar to the following:

    def foo(x):
        if int(x)!=4:
            x = raw_input("Wrong guess, please enter new value: " )
            foo(x)
        else:
            print "Good Job! %s was right"%x
        return x

    value = foo(x=raw_input("Guess a Number between 1 and 10: "))
    print value

If I enter, for instance: "1" then "2" then "3" then "4", I get the following printed out:

Good Job! 4 was right
2

This is confusing, since it seems the function is successfully identifying the right answer, but after doing so it is returning a value that was the 2nd response given, instead of the most recent response.

Can anyone explain what's going on with the binding of "x" in this recursive function?

like image 959
arkansasred Avatar asked May 20 '26 02:05

arkansasred


2 Answers

Let's see!

value = foo(raw_input())
# foo is the same as in the question, I won't repeat it here
print value

Inside your foo, you get this:

# foo(1) calls foo(2) and sets x to 2
# foo(2) calls foo(3) and sets x to 3
# foo(3) calls foo(4) and sets x to 4
# foo(4) does:
print "Good Job! 4 was right"
return 4 # to foo(3)
# foo(3) does:
return 4 # to foo(2)
# foo(2) does:
return 3 # to foo(1)
# foo(1) does:
return 2 # to main

Since the return value to main (from the outermost recursion) is 2, that's what value remains.

To fix this, you can either make it iterative:

def iter_foo(x):
    while int(x) != 4:
        x = raw_input("Wrong guess. Try again! ")
    print "Good Job! %s was right" % x
    return x

Or make EACH recursion return the result of the new function

def recurse_foo(x):
    if int(x) != 4:
        return foo(raw_input("Wrong guess. Try again! "))
    else:
        print "Good Job! %s was right!" % x
        return x
like image 120
Adam Smith Avatar answered May 22 '26 17:05

Adam Smith


So it's mostly because you are missing a return in

def foo(x):
    if int(x)!=4:
        x = raw_input("Wrong guess, please enter new value: " )
        foo(x) # <-- need return
    else:
        print "Good Job! %s was right"%x
    return x

value = foo(x=raw_input("Guess a Number between 1 and 10: "))
print value

What's happening is it calls foo(1), which is not equal to 4, assigns x to 2, and that is the last value that x gets assigned to, so

  • Your recursive foo(x) returns a value, but it isn't assigned to anything or returned from the recursive call.
  • The last value x received was 2, so that is what the initial foo(1) returns

So either

x = foo(x)

Or

return foo(x)

On the line I highlighted

like image 25
C.B. Avatar answered May 22 '26 16:05

C.B.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!