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

为何在LeetCode题中需用nonlocal避免UnboundLocalError?

为什么Python闭包里需要用nonlocal访问外层变量?

先给你捋清楚Python和JavaScript在闭包变量作用域上的核心差异,就能明白为啥必须加nonlocal了:

1. Python的变量赋值规则

Python里有个关键规则:如果函数内部对某个变量执行了赋值操作(比如res += node.val本质是res = res + node.val),Python会默认把这个变量当成当前函数的局部变量,哪怕外层作用域已经定义了同名变量。

回到你的代码:如果去掉nonlocal res,dfs函数里的res += node.val会触发Python的局部变量判定——它会认为res是dfs自己的局部变量,但你在赋值之前根本没在dfs里定义过res,自然就会抛出UnboundLocalError。

2. JavaScript的闭包逻辑

JS的规则不一样:内层函数可以直接访问外层函数的变量,而且只要你没有在内部用var/let/const重新声明同名变量,修改外层变量的操作(比如res += ...)就会直接作用于外层的那个变量,不会触发局部变量的重新声明。这就是你在JS里不用额外关键字就能实现闭包修改的原因。

3. 再看你的代码里nonlocal的作用

nonlocal res这句话就是明确告诉Python:「这个res不是我dfs函数的局部变量,你去上一层的作用域(也就是rangeSumBST函数的作用域)找它」。这样Python就不会把res当成dfs的局部变量,修改操作就能正确作用于外层定义的res了。

替代方案(不用nonlocal的写法)

如果你不想用nonlocal,也可以用可变类型(比如列表)来存储结果,因为修改可变类型的元素不需要声明变量作用域:

class Solution:
    def rangeSumBST(self, root: Optional[TreeNode], low: int, high: int) -> int:
        res = [0]  # 用列表存,因为列表是引用类型
        
        def dfs(node):
            if not node:
                return
            if low <= node.val <= high:
                res[0] += node.val
            dfs(node.left)
            dfs(node.right)
        
        dfs(root)
        return res[0]

不过这种写法可读性不如用nonlocal直接明了,还是推荐用nonlocal的写法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 15:24:24