Search code examples
pythonfunctionrecursionpython-bindings

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?


Solution

  • 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