Python: Unexpected behaviour of nonlocal variable in recursion

Question:

The following code is expected to set the nonlocal variable flag to true after 3 calls to recur(). I expect flag in the following code to be always true after recur(2) returns (starting from 0)

def f():
    flag = False
    def recur(n):
        nonlocal flag
        print(f"this is recur {n}")
        print("flag is: ", flag)
        if n == 2: 
            print(f"end of recur {n}")
            print("flag is: ", flag)
            return True
        flag = flag or recur(n+1) # the culprit line
        
        print(f"end of recur {n}")
        print("flag is: ", flag)
        return False
    recur(0)
f()

However, flag jumps from true to false when recur(1) returns. The output of the function is as follow:

this is recur 0 
flag is: False 
this is recur 1 
flag is: False 
this is recur 2 
flag is: False 
end of recur 2 
flag is: False 
end of recur 1 
flag is: True 
end of recur 0 
flag is: False <-- I expect this to be true

When I change the culprit line to flag = recur(n+1) or flag, the code works as expected, i.e. flag will always be true after recur(2) returns.

I suspect it has something to do with short-circuiting of or, but still I am totally confused. Please help.

Asked By: stackUnderflow

||

Answers:

In flag = flag or recur(n+1), the LHS of the or is evaluated before recur(n+1). When recur(0) executes this line, it evaluates flag and gets False before calling recur(1).

By the time recur(1) returns, flag is True, but the LHS of the or has already been evaluated, so the or evaluates False or False and gets False, not True.

Short-circuiting would also come into play if the LHS of the or was evaluated as True, but that never happens in this code.

Answered By: user2357112