作用域规则

5.4 作用域规则

Python 查找变量的顺序:局部 → 外层函数 → 全局 → 内置。

LEGB 规则:Local(局部)、Enclosing(外层)、Global(全局)、Built-in(内置)。

只在读取变量时按 LEGB 顺序查找;赋值默认创建局部变量。

循环和 if 语句不创建新作用域,其中的变量在外部也能用。

💡 小项目全局变量没问题,大项目建议把相关函数和数据封装成类。
💡 列表、字典等可变对象,在函数内修改元素要小心,可能意外影响其他地方。
💡 养成好习惯:先定义后使用,全局变量用大写标记。

LEGB 查找顺序

嵌套函数中,内层函数可以读取外层和全局变量。

# ========================================
# 示例:LEGB 查找顺序
# 说明:Python 按 LEGB 顺序查找变量
# ========================================
global_var = '全局'

def outer():
    outer_var = '外层'
    
    def inner():
        inner_var = '内层'
        # 先找局部(inner_var),找不到找外层(outer_var)
        print(inner_var)   # 内层:找到
        print(outer_var)   # 外层:找到
        print(global_var)  # 全局:找到
    
    inner()
    # print(inner_var)  # 错误!inner_var 是 inner 的局部变量

outer()

循环变量的作用域

循环和 if 不会创建新作用域,其中的变量外部可见。

# ========================================
# 示例:循环变量的作用域
# 说明:for 循环的变量在循环后还能用
# ========================================
for i in range(3):
    print(i)
# i 在循环结束后仍然存在
print('循环外的 i =', i)  # i = 2(最后一个值)

if True:
    flag = True
print('if 外的 flag =', flag)  # flag 也能用

列表在内外共享

修改列表/字典元素不需要 global,但重新赋值会创建局部变量。

# ========================================
# 示例:列表在内外共享
# 说明:列表是引用类型,函数内修改会影响全局
# ========================================
names = ['小明', '小红']  # 全局列表

def add_name():
    names.append('小刚')  # 修改原列表,不需要 global

print('修改前:', names)
add_name()
print('修改后:', names)  # 列表被改变了

# 但赋值会创建局部变量,不会改变全局列表:
def reset():
    names = ['新学生']  # 这是新局部列表,不影响全局

reset()
print('reset后:', names)  # 还是原来的列表

⚠️ 常见错误与正确对比

❌ 错误写法
x = [1, 2]
def func():
    x.append(3)  # 看似修改全局,但会被当成局部
    x = [4]      # 这行导致 x.append 报错
✅ 正确写法
x = [1, 2]
def func():
    global x
    x.append(3)
    x = [4]

📌 函数内对变量赋值后,该变量变成局部变量,导致前面也变成局部报错。