WeakLearner
WeakLearner

Reputation: 938

scoping of recursive functions within functions in python

Why does the following work:

def rec(a, b, c):
    global nmb_calls
    nmb_calls += 1
    # other stuff
    rec(...)

p_list = []
nmb_calls = 0 
rec(a=p_list, b, c)
print(p_list)

but something like:

def rec(a, b, c):
    nonlocal nmb_calls
    nmb_calls += 1
    # other stuff
    rec(...)

def call_rec(usr_b):
    p_list = []
    nmb_calls = 0
    rec(a=p_list, b=usr_b, c)
    return p_list

fail with the error: SyntaxError: no binding for nonlocal 'nmb_calls' found

I thought nonlocal means that rec would look up in the enclosing scope (that of call_rec), find nmb_calls and use that?

Upvotes: 1

Views: 249

Answers (1)

Nick Weseman
Nick Weseman

Reputation: 1532

The reason the second case doesn't work is the way you're calling it in call_rec is not an enclosing scope that works with nonlocal. You'd have to do something like the following to call rec() using nonlocal for nmb_calls:

def enclosing_function():
    def rec(a, b, c):
        nonlocal nmb_calls
        nmb_calls += 1
        # other stuff
        #rec(...)

    p_list = []
    nmb_calls = 0
    rec(a=p_list, b=usr_b, c=None)
    return p_list

Also, just a heads up that you can't call rec without specifying the c parameter in the same way as you did for a and b.

So this doesn't work:

rec(a=p_list, b=usr_b, c)

but you can do the reverse:

rec(a, b, c=None)

Upvotes: 2

Related Questions