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. 循环、条件语句不创建新作用域

相关推荐
用户8356290780513 小时前
Python 操作 PDF 附件:添加、查看与管理指南
后端·python
宇宙之一粟11 小时前
乐企版式文件生成平台
java·后端·python
学测绘的小杨1 天前
CompassFusion:一个从 GNSS 到 GNSS/INS 组合导航的独立工程包
python
zzzzzz3101 天前
当产品经理说这个很简单:我用Python自动化处理奇葩需求的实战指南
python·pycharm·产品经理
雪隐1 天前
个人电脑玩AI-06让5060 Ti给你打工——不光能画画,Qwen3-TTS还能学人说话,连我老板都信了!
人工智能·后端·python
兵慌码乱2 天前
面向桌面端的资产管理系统分层架构设计与核心模块实现
python·系统架构·sqlite·pyqt5·数据库设计·桌面应用开发·mvc架构
hboot2 天前
AI工程师第三课 - 机器学习基础
python·scikit-learn·kaggle
顾林海2 天前
Agent入门阶段-编程基础-Python:流程控制
python·agent·ai编程
呱呱复呱呱2 天前
Django CBV 源码解读:一个请求是怎么找到你的 get() 方法的
python·django
曲幽2 天前
刚部署的 LibreTranslate 频频翻车?我掏出了 20 年前的 StarDict 词典,用 FastAPI 搭了个本地词典翻译 API
python·fastapi·web·translate·goldendict·libretranslate·stardict·pystardict