You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python嵌套函数修改外层布尔变量报错,用列表却正常?

问题:嵌套函数修改外层布尔变量报错,但使用列表却正常?

下面是一段判断二叉树是否平衡的Python代码,它用列表类型balanced标记树是否平衡,运行正常:

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]

但如果把第3行改成balanced = True,并将第6、13、19行的balanced[0]替换为balanced,程序就会报错。

我测试了另一段代码,发现嵌套函数能正常读取外层的布尔变量c:

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

这段代码输出sum is: (12, True),说明嵌套函数可以访问外层变量。那为什么前一种场景修改布尔变量会报错,用列表就没问题?


原因解析

这其实是Python的变量作用域规则和可变/不可变类型差异共同导致的:

  • 读取 vs 修改的作用域规则
    嵌套函数可以直接读取外层作用域的变量(比如你测试代码里的c),但如果要修改外层变量,Python默认会把这个变量当成嵌套函数的局部变量——除非你用nonlocal(针对嵌套外层的变量)或global(针对全局变量)声明它的来源。
    当你把balanced改成布尔值后,在node_height里执行balanced = False时,Python会认为你是在定义一个局部变量balanced,但这个变量在赋值前就被if not balanced引用了,所以会抛出UnboundLocalError(局部变量在赋值前被引用)。

  • 可变类型 vs 不可变类型的区别
    布尔值、整数、字符串都是不可变类型:你没法直接修改它们的内部值,只能重新赋值(相当于创建一个新对象)。
    列表是可变类型:你可以修改列表内部的元素(比如balanced[0] = False),这并不会重新给balanced变量赋值,只是修改了它指向的列表对象的内容。所以Python不会把balanced当成嵌套函数的局部变量,而是继续引用外层作用域的那个列表。

  • 不用列表的解决方法
    如果不想用列表,你可以用nonlocal声明告诉Python:这个变量不是局部的,来自外层作用域。修改后的代码如下:

class Solution:
    def isBalanced(self, root: Optional[TreeNode]) -> bool:
        balanced = True
        
        def node_height(root):
            nonlocal balanced
            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
                return 0
            
            return 1 + max(left_height, right_height)
            
        node_height(root)
        return balanced

这样修改后,布尔变量的版本也能正常运行。


内容的提问来源于stack exchange,提问作者DHK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 17:22:07