问题: 闭包中外部函数的变量,内部函数可以直接修改吗?
👇 点击展开/折叠 面试背诵模板(建议先背这个)
闭包中内层函数不能直接修改外层函数的变量。直接赋值会将其视为内层函数的局部变量,抛出 UnboundLocalError。若需修改,必须用 nonlocal 关键字显式声明该变量来自外层作用域。只读访问(如读取、调用方法)不需要 nonlocal。
---
错误示例 vs 正确示例 1 2 3 4 5 6 7 8 9 10 def outer (): count = 0 def inner (): count += 1 return count return inner c = outer() c()
1 2 3 4 5 6 7 8 9 10 11 12 def outer (): count = 0 def inner (): nonlocal count count += 1 return count return inner c = outer() print (c()) print (c())
修改变量的三种场景对比
操作类型
是否需要 nonlocal
示例
读取外层变量
❌ 不需要
return x
调用外层变量的方法(不重新赋值)
❌ 不需要
lst.append(1)
重新赋值(=、+=、-= 等)
✅ 必须用 nonlocal
count += 1
重新赋值整个变量(如 x = 10)
✅ 必须用 nonlocal
nonlocal x; x = 10
为什么需要 nonlocal? Python 在编译函数体时,如果某个变量在函数内部被赋值(= 左边出现),则默认将其视为局部变量 。count += 1 等价于 count = count + 1,对 count 进行了赋值,于是 Python 认为 count 是 inner 的局部变量,但赋值右侧的 count 还未定义,因此报错。nonlocal 告诉 Python:这个变量不在本函数定义,去外层函数中找。
nonlocal vs global 对比
关键字
作用域
查找链
使用场景
nonlocal
最近的外层函数(非全局)
跳过本地 → 逐层向外找,直到全局之前
闭包中修改外层变量
global
全局作用域
跳过本地 → 直接找全局
函数中修改全局变量
常见陷阱:多层嵌套时的 nonlocal 1 2 3 4 5 6 7 8 9 10 11 12 13 def outer (): x = 1 def middle (): x = 2 def inner (): nonlocal x x += 1 return x return inner return middle f = outer()() print (f())