global只修改模块顶层变量,嵌套函数中修改外层变量须用nonlocal;赋值前必须声明,否则默认创建局部变量导致unboundlocalerror。

global 修改的是模块顶层变量,不是“所有外层”
很多人以为 global 能让函数修改上一级函数的变量,其实它只认模块级(即文件最外层)定义的变量。如果嵌套了两层函数,中间那层的变量对内层来说既不是局部也不是全局——这时候 global 无效,必须用 nonlocal。
- 写
global x后再赋值x = 5,只会修改模块级的x,哪怕外层函数里也有个同名x,它完全不受影响 - 若外层函数定义了
x,而你想在内层函数中修改它,必须写nonlocal x,否则直接赋值会创建新的局部变量 -
global声明不检查变量是否存在;首次赋值时才会在模块命名空间创建该变量
nonlocal 只能向上找一层或多层嵌套作用域,不能跨到模块层
nonlocal 的搜索范围严格限定在**最近的、非全局的 enclosing scope** 中。它不会继续往上找到模块变量,也不会跳过某一层去匹配更外层的同名变量。
- 如果嵌套三层函数,最内层用
nonlocal x,Python 会从直接外层开始找;找不到就报SyntaxError: no binding for nonlocal 'x' found - 不能用
nonlocal声明一个模块级变量;那样会直接报错,必须改用global - 同一个
nonlocal语句可声明多个变量:nonlocal a, b, c,但它们必须全部存在于同一层 enclosing scope 中
赋值前必须声明 global/nonlocal,否则 Python 默认创建局部变量
这是最容易踩的坑:只要你在函数里对某个变量做了赋值(比如 x = x + 1),Python 就默认它是局部变量——哪怕外层已有同名变量。此时不加声明,运行时会抛 UnboundLocalError: local variable 'x' referenced before assignment。
- 错误写法:
def outer(): x = 10 def inner(): print(x) # ✅ 读取没问题 x = 20 # ❌ 这行让 x 变成局部变量,上一行就报错 inner() - 正确写法(想改外层):
nonlocal x必须出现在函数体开头附近,且在任何对该变量的读/写操作之前 - 读取不需声明,只有**写入(赋值)** 才触发局部变量绑定逻辑
闭包中修改自由变量时,nonlocal 是唯一安全方式
当函数返回内嵌函数(形成闭包),且希望后续调用能持续更新外层变量时,nonlocal 不仅是语法要求,更是语义必需。不用它,每次调用都只能读旧值或写新局部副本。
- 常见场景:计数器工厂、状态缓存、回调配置项更新
- 示例:
def make_counter(): count = 0 def counter(): nonlocal count count += 1 return count return counter <p>c = make_counter() print(c()) # 1 print(c()) # 2 —— 状态被真实保留</p> - 如果漏掉
nonlocal count,第二次调用会报UnboundLocalError,因为count += 1被解析为count = count + 1,而右侧的count此时已被判定为局部变量
真正容易被忽略的是:global 和 nonlocal 都不能动态生效,必须在编译期确定作用域链。这意味着你不能靠条件判断来决定是否声明——语法错误会在 import 或定义函数时就抛出,而不是运行到那行才报。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











