pythonfunctionnested

using variable out of nested function


class Solution:
    def isBalanced(self, root: Optional[TreeNode]) -> bool:
        balanced = [True]
        
        def node_height(root):
            if not root or not balanced[0]:
                return 0
            
            left_height = node_height(root.left)
            right_height = node_height(root.right)
            
            if abs(left_height - right_height) > 1:
                balanced[0] = False
                return 0
            
            return 1 + max(left_height, right_height)
            
        node_height(root)
        return balanced[0]

I understand why the code above works but when I change the value of variable 'balanced' to balanced = True instead of balanced = [True] in line 3 and change balanced[0] to balanced in line 6, 13 and 19, I get an error.

class solution:
    def func(): 
        a = 5
        b = 7
        c = True
        def nested_func():
            return (a + b, c)
        return nested_func()
        
    print('sum is:', func())

So I tried the code above to test (maybe nested function cannot get variable that has boolean as a value) but was able to get the result of 'sum is: (12, True)' which shows that nested functions are able to get variables outside of them.

Could someone explain this?


Solution

  • Nested functions can access variables from their parent functions. However, in your first case, not only you are accessing the value of the balanced variable, but you are also attempting to modify it.

    Whenever you create a variable in a nested function with the same name as a variable in the parent function, the nested function uses its own variable that is created inside the nested function.

    So in this code

        def node_height(root):
            if not root or not balanced:
                return 0
            
            left_height = node_height(root.left)
            right_height = node_height(root.right)
            
            if abs(left_height - right_height) > 1:
                balanced = False #  You are creating the variable here, 
                                 #  but you are trying to access it above in the first if-else statement. 
                                 # That is why you are getting the UnboundlocalError
                return 0
            
            return 1 + max(left_height, right_height)
    

    And about the first list approach, as you know list are mutable so you can update them inside the function, and it will update in all scope, so that is why it was working.


    And in this example, As already Answered by Aemyl and mentioned by me above ("Nested functions can access variables from their parent functions."), In this code you are not updating the value instead you are just accessing the value of the parent's variable(s), so that is why you are not getting any error.

    class solution:
        def func(): 
            a = 5
            b = 7
            c = True
            def nested_func():
                return (a + b, c)
            return nested_func()
            
        print('sum is:', func())