📚 Python 全局变量使用学习笔记

适用场景:模块级配置、缓存模型、单例状态管理等
核心原则:理解“变量绑定”与“对象修改”的区别


一、全局变量的定义

在模块顶层(函数外)定义的变量就是全局变量:

my_global = "hello"
config = {"debug": True}
cache = {}

这些变量在整个模块中都可访问。


二、在函数中使用全局变量的三种情况

情况 是否需要 global 示例 说明
✅ 1. 只读访问 ❌ 不需要 print(my_global) 可直接读取
✅ 2. 修改可变对象内容 ❌ 不需要 cache["key"] = value
config.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

六、最佳实践建议

推荐做法

  1. 避免滥用全局变量,优先使用函数参数或类封装。
  2. 模块级状态统一管理,如创建 model_manager.py 集中加载。
  3. 只读全局配置:用大写命名,如 CONFIG = {...}
  4. 可变全局状态:用 dictlist,通过方法修改内容,避免频繁 global
  5. 启动时预加载:如模型、配置,在 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 吗?

✅ 答案:

  1. ❌ 会报错(UnboundLocalError),因为 += 是赋值
  2. ✅ 成功,修改 list 内容
  3. ✅ 因为 counter = 0 是重新绑定变量
  4. ❌ 不需要,clear() 是修改对象内容

✅ 总结

操作 是否需要 global
print(x)
my_dict[key] = value
my_list.append(x)
x = ...
x += 1 ✅(等价于 x = x + 1

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐