page contents

Python变量作用域全解析:从局部到全局,彻底掌握LEGB规则

变量作用域是指变量可被访问的代码范围。与 Java 等语言不同,Python 的变量作用域规则更灵活,尤其在全局变量和局部变量的区分上有特殊机制。本文将详细解析 Python 中变量的作用域类型、访问规则及修改全局变量的方法。

attachments-2026-06-CWxC9QeW6a431e097fab1.png

变量作用域是指变量可被访问的代码范围。与 Java 等语言不同,Python 的变量作用域规则更灵活,尤其在全局变量和局部变量的区分上有特殊机制。本文将详细解析 Python 中变量的作用域类型、访问规则及修改全局变量的方法。

作用域的基本类型

Python 中变量的作用域分为以下四种,按访问优先级从高到低排列:

局部作用域(Local):在函数内部定义的变量,仅在函数内有效。

嵌套作用域(Enclosing):在嵌套函数外层的函数中定义的变量(适用于闭包场景)。

全局作用域(Global):在模块(.py 文件)顶层定义的变量,整个模块内可访问。

内置作用域(Built-in):Python 内置的变量或函数(如 print、len)。

查找顺序:L → E → G → B(由内向外)

局部变量(Local)

在函数内部定义的变量默认为局部变量,仅在函数执行期间存在,函数外部无法访问。

示例:局部变量的特性

# 全局变量 x
x = 50

def function_local(x_param):
    # 函数内部的 x 是局部变量(参数也是局部变量)
    print(f"函数内初始 x(参数):{x_param}")
    x_local = 2# 局部变量
    print(f"函数内修改后局部 x:{x_local}")

# 调用函数
function_local(x)

# 函数外部无法访问局部变量
print(f"函数外全局 x:{x}")  # 输出:50(不受函数内局部变量影响)
# print(x_local)  # 报错:NameError: name 'x_local' is not defined

输出结果:

函数内初始 x(参数):50
函数内修改后局部 x:2
函数外全局 x:50

结论:

函数参数(如 x_param)也是局部变量。

函数内部定义的变量(如 x_local)仅在函数内有效。

局部变量与全局变量同名时,函数内优先使用局部变量。

全局变量(Global)

在模块顶层定义的变量为全局变量,可在模块内的任何函数外访问。若要在函数内修改全局变量,需用 global 关键字声明。

访问全局变量(无需声明)

函数内可直接访问全局变量(无需 global 声明):

# 全局变量
greeting = "Hello"

def print_greeting():
    # 直接访问全局变量
    print(greeting)

print_greeting()  # 输出:Hello

修改全局变量(需用 global 声明)

若在函数内直接修改全局变量,Python 会将其视为局部变量(创建新的局部变量),而非修改全局变量。如需修改,必须用 global 声明:

# 全局变量
count = 0

def increment():
    # 声明使用全局变量 count(而非创建局部变量)
    global count
    count += 1  # 修改全局变量
    print(f"函数内 count:{count}")

increment()  # 输出:函数内 count:1
print(f"函数外 count:{count}")  # 输出:函数外 count:1(全局变量已被修改)

**如果不声明 global**:

count = 0

def increment_error():
    count += 1  # 报错:UnboundLocalError(Python 认为 count 是局部变量,但未初始化)

increment_error()

global 关键字的作用

告诉 Python:“该变量是全局变量,不要创建局部变量”。

global 声明必须放在变量使用之前。

name = "Alice"

def change_name():
    global name  # 声明在使用前
    name = "Bob"  # 修改全局变量

change_name()
print(name)  # 输出:Bob

嵌套作用域(Enclosing)

当函数嵌套时,内层函数可访问外层函数的变量(非全局),这种作用域称为嵌套作用域。若要修改外层函数的变量,需用 nonlocal 关键字(Python 3 新增)。

示例:嵌套函数与 nonlocal

def outer():
    # 外层函数的变量(嵌套作用域)
    message = "Hello from outer"

    def inner():
        # 声明使用外层函数的 message(非局部,非全局)
        nonlocal message
        message = "Hello from inner"  # 修改外层变量
        print(f"内层函数:{message}")

    inner()
    print(f"外层函数:{message}")  # 输出修改后的值

outer()

输出结果:

内层函数:Hello from inner
外层函数:Hello from inner

说明:

若不用 nonlocal,内层函数的 message 会被视为局部变量。

nonlocal 仅用于嵌套作用域,不可用于全局变量。

闭包(Closure)

当内层函数返回并被外部使用时,外层函数的变量会被“记住”,这就是闭包。

def make_multiplier(n):
    """创建一个乘以 n 的函数"""
    def multiplier(x):
        return x * n        # n 来自外层函数
    return multiplier

# 创建两个不同的闭包
double = make_multiplier(2)
triple = make_multiplier(3)

print(double(5))    # 10
print(triple(5))    # 15
print(triple(10))   # 30

# 查看闭包捕获的变量
print(double.__closure__[0].cell_contents)  # 2

内置作用域(Built-in)

Python 内置的名称

Python 预定义了一些内置函数和异常,它们位于 builtins 模块中。

# 常用内置函数
print(len([1, 2, 3]))       # 3
print(max(10, 20, 30))      # 30
print(type(42))             # <class 'int'>

# 查看所有内置名称
# import builtins
# print(dir(builtins))

内置作用域被遮蔽的问题

如果不小心定义了与内置函数同名的变量,会“遮蔽”内置函数。

# ⚠️ 严重问题:遮蔽了内置的 len 函数
len = 100                   # 创建了全局变量 len

def get_length(items):
    return len(items)       # ❌ TypeError: 'int' object is not callable

# 恢复:删除自己定义的 len
del len
print(len([1, 2, 3]))       # 3(恢复)

最佳实践:避免使用内置名称作为变量名(如 len、list、dict、str、type 等)

作用域查找规则:LEGB 原则

当访问一个变量时,Python 按以下顺序查找:

L(Local):当前函数内部的局部变量。

E(Enclosing):外层函数的变量(嵌套作用域)。

G(Global):模块顶层的全局变量。

B(Built-in):Python 内置的变量或函数。

若找不到变量,会抛出 NameError。

示例:LEGB 原则演示

# 全局变量(G)
x = "global"

def outer():
    # 嵌套作用域变量(E)
    x = "outer"

    def inner():
        # 局部变量(L)
        x = "inner"
        print(x)  # 优先使用局部变量(L)→ 输出:inner

    inner()
    print(x)  # 外层变量(E)→ 输出:outer

outer()
print(x)  # 全局变量(G)→ 输出:global

# 访问内置函数(B)
print(len([1, 2, 3]))  # 调用内置的 len 函数 → 输出:3

常见问题与最佳实践

 

避免滥用全局变量:

 

全局变量会增加函数间的耦合,降低代码可读性。

优先通过函数参数传递数据,而非依赖全局变量。

 

**区分 global 和 nonlocal**:

 

global:用于修改全局变量(模块顶层)。

nonlocal:用于修改嵌套作用域的变量(外层函数)。

 

局部变量遮蔽(Shadowing):

 

x = 100
def shadow():
    x = 200  # 局部变量,遮蔽全局 x
    print(x)  # 输出:200
shadow()
print(x)  # 输出:100(全局 x 未变)

 

若局部变量与全局变量同名,局部变量会 “遮蔽” 全局变量(函数内优先使用局部)。

更多相关技术内容咨询欢迎前往并持续关注好学星城论坛了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg

 

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
Pack
Pack

2179 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 2228 文章
  3. Pack 2179 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章