Python 中的 4 种作用域

Python 的作用域遵循 LEGB 规则 ,即:L → E → G → B(由内向外查找)。

一、四种作用域

作用域 英文 说明 示例
Local 局部作用域 函数内部定义的变量 def func(): x = 1
Enclosing 闭包/嵌套作用域 外层嵌套函数的变量 嵌套函数中访问外层函数的变量
Global 全局作用域 模块顶层定义的变量 脚本中 x = 1
Built-in 内置作用域 Python 内置的名称 print()len()range()

二、详细说明

1. Local(局部作用域)

函数内部定义的变量,只能在函数内部访问。

复制代码
def my_func():
    x = 10  # 局部变量
    print(x)  #  可以访问

my_func()
# print(x)  #  NameError: name 'x' is not defined

特点

  • 函数调用时创建,函数返回时销毁

  • 不同函数的局部变量互不干扰

    def func_a():
    x = 10
    return x

    def func_b():
    x = 20 # 与 func_a 的 x 不同,互不影响
    return x

    print(func_a()) # 10
    print(func_b()) # 20

2. Enclosing(闭包/嵌套作用域)

在嵌套函数中,内层函数可以访问外层函数的变量。

复制代码
def outer():
    x = 10  # enclosing 变量
    
    def inner():
        print(x)  #  可以访问外层变量
    
    inner()

outer()  # 10
修改 enclosing 变量
复制代码
def outer():
    x = 10
    
    def inner():
        nonlocal x  # 声明要修改外层变量
        x = 20
    
    inner()
    print(x)  # 20

outer()

3. Global(全局作用域)

在模块顶层定义的变量,可以在整个模块中访问。

复制代码
x = 10  # 全局变量

def my_func():
    print(x)  #  可以访问全局变量

my_func()  # 10
修改全局变量
复制代码
x = 10

def my_func():
    global x  # 声明要修改全局变量
    x = 20

my_func()
print(x)  # 20
模块级别的全局变量
复制代码
# file: config.py
MAX_SIZE = 100
DATABASE_URL = "sqlite:///db.sqlite"

# file: main.py
import config
print(config.MAX_SIZE)  # 100

4. Built-in(内置作用域)

Python 预定义的名称,在任何地方都可以直接使用。

复制代码
# 内置函数
print("Hello")
len([1, 2, 3])
range(5)

# 内置异常
ValueError
TypeError

# 内置常量
True
False
None
查看所有内置名称
复制代码
print(dir(__builtins__))
# ['ArithmeticError', 'AssertionError', 'BaseException', ...]

三、作用域规则

1. 变量查找顺序(LEGB)

复制代码
x = "global"  # Global

def outer():
    x = "enclosing"  # Enclosing
    
    def inner():
        x = "local"  # Local
        print(x)     # 输出: local(先找到 Local)
    
    inner()

outer()  # local

2. 逐级查找过程

复制代码
x = "global"

def outer():
    x = "enclosing"
    
    def inner():
        # 1. 先查 Local → 没有 x
        # 2. 再查 Enclosing → 有 x = "enclosing"
        # 3. 不会继续往上查
        print(x)  # 输出: enclosing
    
    inner()

outer()

3. 不同作用域同名变量的遮蔽

复制代码
x = "global"      # Global

def outer():
    x = "enclosing"   # Enclosing(遮蔽 Global)
    
    def inner():
        x = "local"   # Local(遮蔽 Enclosing)
        print(x)
    
    inner()
    print(x)  # enclosing

outer()
print(x)  # global

四、作用域相关关键字

1. global 关键字

用于在函数内部修改全局变量。

复制代码
count = 0

def increment():
    global count  # 声明 count 是全局变量
    count += 1

increment()
print(count)  # 1

2. nonlocal 关键字

用于在嵌套函数中修改外层函数的变量。

复制代码
def outer():
    x = 10
    
    def inner():
        nonlocal x  # 声明 x 是外层变量
        x = 20
    
    inner()
    print(x)  # 20

outer()

3. 常见错误:忘记声明

复制代码
x = 10

def func():
    # 错误!这会在局部作用域创建新变量,不会修改全局变量
    x = 20  # 这是局部变量,不是修改全局

func()
print(x)  # 10(全局变量未被修改)

x = 10

def func():
    global x  # 正确
    x = 20

func()
print(x)  # 20

五、作用域与数据类型

1. 可变对象的修改不需要 global

复制代码
my_list = [1, 2, 3]

def append_item():
    # 修改列表内容,不需要 global
    my_list.append(4)

append_item()
print(my_list)  # [1, 2, 3, 4]

# 但如果要重新赋值,就需要 global
def reassign():
    global my_list
    my_list = [5, 6, 7]  # 重新赋值

2. 不可变对象必须用 global

复制代码
count = 0

def increment():
    global count
    count += 1  # 整数是不可变对象,需要重新赋值

六、注意事项

1. 条件语句不创建作用域

复制代码
if True:
    x = 10  # 即使缩进,x 还是在全局作用域

print(x)  # 10(不是错误!)

for i in range(5):
    pass

print(i)  # 4(循环变量会泄露到外层)

七、对比表

作用域 位置 访问方式 修改关键字
Local 函数内部 直接访问 -
Enclosing 外层嵌套函数 直接访问(读) nonlocal(写)
Global 模块顶层 直接访问(读) global(写)
Built-in Python 内置 直接访问 不能修改

查找顺序

LEGB:Local → Enclosing → Global → Built-in

修改规则

读变量,按 LEGB 找;写变量,默认只在 Local 改。

想改外层用 nonlocal,想改全局用 global。

核心点

  1. Python 使用 静态作用域(词法作用域)

  2. 变量赋值默认在当前作用域创建/修改

  3. 访问变量按 LEGB 顺序查找

  4. globalnonlocal 用于修改外层变量

  5. 循环、条件语句不创建新作用域

相关推荐
coderwei1232 小时前
从OpenAI到Strip:用六大支柱读懂Harness Engineering的生产实践
python·ai·ai编程
海鸥-w2 小时前
Python(FastAPI)中ORM框架Sqlalchemy的安装及建表
python
Wonderful U2 小时前
Python+Django实战|个人博客内容管理系统:搭建轻量化、高自由度的个人动态博客CMS系统
人工智能·python·django
高洁013 小时前
智能体:你的私人数字助理
人工智能·python·数据挖掘·virtualenv·知识图谱
海鸥-w3 小时前
python(fastapi) 实现更新,新增,删除接口
android·python·fastapi
淘矿人3 小时前
DeepSeek V4对决Claude 4.8:AI模型终极横评
java·开发语言·人工智能·python·sql·php·pygame
showgea3 小时前
Python httpx封装和使用
python·httpx
Asize3 小时前
重生之我在 Vibe Coding 时代当程序员:第十二课,Prompt 不是咒语,是可以沉淀的业务接口
前端·人工智能·python
abigale033 小时前
字典 与 Python 对象 的总结
python·dict·object