Python 全局变量使用
·
📚 Python 全局变量使用学习笔记
适用场景:模块级配置、缓存模型、单例状态管理等
核心原则:理解“变量绑定”与“对象修改”的区别
一、全局变量的定义
在模块顶层(函数外)定义的变量就是全局变量:
my_global = "hello"
config = {"debug": True}
cache = {}
这些变量在整个模块中都可访问。
二、在函数中使用全局变量的三种情况
| 情况 | 是否需要 global |
示例 | 说明 |
|---|---|---|---|
| ✅ 1. 只读访问 | ❌ 不需要 | print(my_global) |
可直接读取 |
| ✅ 2. 修改可变对象内容 | ❌ 不需要 | cache["key"] = valueconfig.update(...) |
修改的是对象内部 |
| ❌ 3. 重新赋值变量 | ✅ 必须加 global |
my_global = "new" |
否则变成局部变量 |
三、关键规则总结
🔑 规则 1:赋值(=)即局部
只要你在函数内对变量使用了
=,Python 就认为它是局部变量,除非声明global。
x = 10
def bad():
x = 20 # ❌ 错误:x 被当作局部变量,但未声明 global
✅ 正确写法:
def good():
global x
x = 20 # ✅ 修改全局 x
🔑 规则 2:修改可变对象内容,不需要 global
如果变量指向的是可变对象(如 list, dict, set),修改其内容不需要 global:
cache = {}
config = {"model": None}
def load():
cache["model1"] = "loaded" # ✅ 可以
config["model"] = "bert-base" # ✅ 可以
cache.update({"model2": "ok"}) # ✅ 可以
👉 原因:你没有改变 cache 这个变量的指向,只是通过它修改了对象内部。
🔑 规则 3:重新绑定变量必须用 global
data = [1, 2, 3]
def reset():
data = [4, 5, 6] # ❌ 错误:创建了局部变量 data
✅ 正确:
def reset():
global data
data = [4, 5, 6] # ✅ 修改全局 data
四、常见误区与陷阱
❌ 误区 1:以为“定义过就不需要 global”
即使变量在外部定义了,函数内赋值仍需
global,否则是局部变量。
❌ 误区 2:混合读取和赋值导致 UnboundLocalError
x = 10
def foo():
print(x) # ❌ 报错!
x = 20
👉 原因:Python 看到 x = 20 → 认为 x 是局部变量 → 但 print(x) 在赋值前使用 → 报错
五、global vs nonlocal 对比
| 关键字 | 作用 | 使用场景 |
|---|---|---|
global |
修改模块级全局变量 | x = ... 在函数外定义 |
nonlocal |
修改外层函数的局部变量 | 闭包中修改 enclosing 作用域 |
x = "global"
def outer():
x = "enclosing"
def inner():
global x # 修改 global 的 x
# nonlocal x # 修改 outer 的 x
x = "changed"
inner()
print(x) # 如果用 nonlocal → "changed";用 global → 不影响 outer 的 x
六、最佳实践建议
✅ 推荐做法:
- 避免滥用全局变量,优先使用函数参数或类封装。
- 模块级状态统一管理,如创建
model_manager.py集中加载。 - 只读全局配置:用大写命名,如
CONFIG = {...}。 - 可变全局状态:用
dict或list,通过方法修改内容,避免频繁global。 - 启动时预加载:如模型、配置,在
lifespan中同步加载即可。
✅ 示例:
_MODELS = {}
def load_model(name, path):
global _MODELS # 只在需要重新赋值 _MODELS 本身时才用
model = load_from_path(path)
_MODELS[name] = model # ✅ 修改 dict 内容,不需要 global
def get_model(name):
return _MODELS[name] # ✅ 只读,不需要 global
七、一句话口诀 🎯
🔔 “读不用 global,改内容也不用;只有赋值=,才需要 global。”
八、练习题(自测)
counter = 0
history = []
def step():
counter += 1 # 1. 会报错吗?
history.append("step") # 2. 能成功吗?
def reset():
global counter
counter = 0 # 3. 为什么这里要 global?
history.clear() # 4. 这里需要 global 吗?
✅ 答案:
- ❌ 会报错(UnboundLocalError),因为
+=是赋值 - ✅ 成功,修改 list 内容
- ✅ 因为
counter = 0是重新绑定变量 - ❌ 不需要,
clear()是修改对象内容
✅ 总结
| 操作 | 是否需要 global |
|---|---|
print(x) |
❌ |
my_dict[key] = value |
❌ |
my_list.append(x) |
❌ |
x = ... |
✅ |
x += 1 |
✅(等价于 x = x + 1) |
更多推荐
所有评论(0)