函数内赋值会触发局部变量创建,Python解释器编译时将有赋值操作的变量默认标记为局部变量;即使存在同名全局变量,也不会被修改,未赋值前读取会报UnboundLocalError。

函数内赋值会触发局部变量创建
Python 解释器在编译函数时,只要看到对某个变量名有赋值操作(比如 x = 5、x += 1、x.append(1)),就默认把它标记为“局部变量”,整个函数体都会按这个假设处理。哪怕同名的全局变量已经存在,也不会被覆盖或修改。
常见错误现象:UnboundLocalError: local variable 'x' referenced before assignment —— 这不是因为你没定义 x,而是解释器已认定它是局部变量,却在赋值前就尝试读取它。
- 只读不写:直接
print(x)没问题,无需global - 一写就变:哪怕只是
x = x + 1或x *= 2,都算“赋值”,必须加global x - 可变对象例外:对
list、dict调用原地方法(如my_list.append(1))不触发重新赋值,所以不强制要global;但若写成my_list = my_list[1:],就是新赋值,必须加
global 声明必须出现在赋值之前且在同一作用域
global 不是“让变量变成全局”,而是“告诉解释器:下面要操作的那个变量名,请去全局作用域里找”。它必须写在函数体开头附近,且不能晚于对该变量的首次引用(尤其是赋值)。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
- 顺序错误:把
global x放在x += 1后面,解释器早已按局部变量编译完毕,声明无效 - 作用域限制:类的方法里用
global是合法的,但它影响的是模块级全局变量,不是实例或类属性 - 多个变量:可用逗号分隔,如
global a, b, counter,但每个名都必须已在模块顶层定义过
替代方案比 global 更推荐
频繁依赖 global 往往说明设计可以优化。它会让状态隐式流动,调试困难,单元测试也难隔离。
立即学习“Python免费学习笔记(深入)”;
- 传参 + 返回:把全局数据当参数传入,修改后返回新值,由调用方决定是否覆盖 —— 最清晰可控
- 封装成类:用实例属性管理状态,
self.data天然可读可写,无需global - 使用
nonlocal:嵌套函数中修改外层函数变量时,用nonlocal替代global,语义更准确 - 配置或单例:真正需要跨函数共享的状态,考虑用模块级常量、配置对象或单例类,而非裸变量
容易被忽略的细节
很多人以为“全局变量能被函数读到,改起来也就差一个关键字”,但实际边界很细:
-
global只对“赋值语句”生效;+=、-=等增强赋值运算符也算赋值,必须声明 - 字符串、整数等不可变类型,任何“修改”本质都是新赋值,所以一定需要
global - 如果函数里既有读又有写,且没加
global,Python 会报错或静默创建局部变量——后者更危险,因为程序看似运行,实则没改到预期位置

















